2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
46 /****************************************************************************
47 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
48 path or anything including wildcards.
49 We're assuming here that '/' is not the second byte in any multibyte char
50 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
52 ****************************************************************************/
54 /* Custom version for processing POSIX paths. */
55 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
57 static NTSTATUS check_path_syntax_internal(char *path,
59 bool *p_last_component_contains_wcard)
63 NTSTATUS ret = NT_STATUS_OK;
64 bool start_of_name_component = True;
65 bool stream_started = false;
67 *p_last_component_contains_wcard = False;
74 return NT_STATUS_OBJECT_NAME_INVALID;
77 return NT_STATUS_OBJECT_NAME_INVALID;
79 if (strchr_m(&s[1], ':')) {
80 return NT_STATUS_OBJECT_NAME_INVALID;
86 if ((*s == ':') && !posix_path && !stream_started) {
87 if (*p_last_component_contains_wcard) {
88 return NT_STATUS_OBJECT_NAME_INVALID;
90 /* Stream names allow more characters than file names.
91 We're overloading posix_path here to allow a wider
92 range of characters. If stream_started is true this
93 is still a Windows path even if posix_path is true.
96 stream_started = true;
97 start_of_name_component = false;
101 return NT_STATUS_OBJECT_NAME_INVALID;
105 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
107 * Safe to assume is not the second part of a mb char
108 * as this is handled below.
110 /* Eat multiple '/' or '\\' */
111 while (IS_PATH_SEP(*s,posix_path)) {
114 if ((d != path) && (*s != '\0')) {
115 /* We only care about non-leading or trailing '/' or '\\' */
119 start_of_name_component = True;
121 *p_last_component_contains_wcard = False;
125 if (start_of_name_component) {
126 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
127 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
130 * No mb char starts with '.' so we're safe checking the directory separator here.
133 /* If we just added a '/' - delete it */
134 if ((d > path) && (*(d-1) == '/')) {
139 /* Are we at the start ? Can't go back further if so. */
141 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
144 /* Go back one level... */
145 /* We know this is safe as '/' cannot be part of a mb sequence. */
146 /* NOTE - if this assumption is invalid we are not in good shape... */
147 /* Decrement d first as d points to the *next* char to write into. */
148 for (d--; d > path; d--) {
152 s += 2; /* Else go past the .. */
153 /* We're still at the start of a name component, just the previous one. */
156 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
168 if (*s <= 0x1f || *s == '|') {
169 return NT_STATUS_OBJECT_NAME_INVALID;
177 *p_last_component_contains_wcard = True;
186 /* Get the size of the next MB character. */
187 next_codepoint(s,&siz);
205 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
207 return NT_STATUS_INVALID_PARAMETER;
210 start_of_name_component = False;
218 /****************************************************************************
219 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
220 No wildcards allowed.
221 ****************************************************************************/
223 NTSTATUS check_path_syntax(char *path)
226 return check_path_syntax_internal(path, False, &ignore);
229 /****************************************************************************
230 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
231 Wildcards allowed - p_contains_wcard returns true if the last component contained
233 ****************************************************************************/
235 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
237 return check_path_syntax_internal(path, False, p_contains_wcard);
240 /****************************************************************************
241 Check the path for a POSIX client.
242 We're assuming here that '/' is not the second byte in any multibyte char
243 set (a safe assumption).
244 ****************************************************************************/
246 NTSTATUS check_path_syntax_posix(char *path)
249 return check_path_syntax_internal(path, True, &ignore);
252 /****************************************************************************
253 Pull a string and check the path allowing a wilcard - provide for error return.
254 ****************************************************************************/
256 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
257 const char *base_ptr,
264 bool *contains_wcard)
270 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
274 *err = NT_STATUS_INVALID_PARAMETER;
278 *contains_wcard = False;
280 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
282 * For a DFS path the function parse_dfs_path()
283 * will do the path processing, just make a copy.
289 if (lp_posix_pathnames()) {
290 *err = check_path_syntax_posix(*pp_dest);
292 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
298 /****************************************************************************
299 Pull a string and check the path - provide for error return.
300 ****************************************************************************/
302 size_t srvstr_get_path(TALLOC_CTX *ctx,
303 const char *base_ptr,
312 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
313 src_len, flags, err, &ignore);
316 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
317 char **pp_dest, const char *src, int flags,
318 NTSTATUS *err, bool *contains_wcard)
320 return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf, req->flags2,
321 pp_dest, src, smbreq_bufrem(req, src),
322 flags, err, contains_wcard);
325 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
326 char **pp_dest, const char *src, int flags,
330 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
331 flags, err, &ignore);
334 /****************************************************************************
335 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
336 ****************************************************************************/
338 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
341 if ((fsp == NULL) || (conn == NULL)) {
342 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
345 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
346 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
352 /****************************************************************************
353 Check if we have a correct fsp pointing to a file.
354 ****************************************************************************/
356 bool check_fsp(connection_struct *conn, struct smb_request *req,
359 if (!check_fsp_open(conn, req, fsp)) {
362 if (fsp->is_directory) {
363 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
366 if (fsp->fh->fd == -1) {
367 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
370 fsp->num_smb_operations++;
374 /****************************************************************************
375 Check if we have a correct fsp pointing to a quota fake file. Replacement for
376 the CHECK_NTQUOTA_HANDLE_OK macro.
377 ****************************************************************************/
379 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
382 if (!check_fsp_open(conn, req, fsp)) {
386 if (fsp->is_directory) {
390 if (fsp->fake_file_handle == NULL) {
394 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
398 if (fsp->fake_file_handle->private_data == NULL) {
405 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
406 const char *name, int name_type)
409 char *trim_name_type;
410 const char *retarget_parm;
413 int retarget_type = 0x20;
414 int retarget_port = NBT_SMB_PORT;
415 struct sockaddr_storage retarget_addr;
416 struct sockaddr_in *in_addr;
420 if (get_socket_port(sconn->sock) != NBT_SMB_PORT) {
424 trim_name = talloc_strdup(talloc_tos(), name);
425 if (trim_name == NULL) {
428 trim_char(trim_name, ' ', ' ');
430 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
432 if (trim_name_type == NULL) {
436 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
437 trim_name_type, NULL);
438 if (retarget_parm == NULL) {
439 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
442 if (retarget_parm == NULL) {
446 retarget = talloc_strdup(trim_name, retarget_parm);
447 if (retarget == NULL) {
451 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
453 p = strchr(retarget, ':');
456 retarget_port = atoi(p);
459 p = strchr_m(retarget, '#');
462 if (sscanf(p, "%x", &retarget_type) != 1) {
467 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
469 DEBUG(10, ("could not resolve %s\n", retarget));
473 if (retarget_addr.ss_family != AF_INET) {
474 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
478 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
480 _smb_setlen(outbuf, 6);
481 SCVAL(outbuf, 0, 0x84);
482 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
483 *(uint16_t *)(outbuf+8) = htons(retarget_port);
485 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
487 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
493 TALLOC_FREE(trim_name);
497 static void reply_called_name_not_present(char *outbuf)
499 smb_setlen(outbuf, 1);
500 SCVAL(outbuf, 0, 0x83);
501 SCVAL(outbuf, 4, 0x82);
504 /****************************************************************************
505 Reply to a (netbios-level) special message.
506 ****************************************************************************/
508 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
510 int msg_type = CVAL(inbuf,0);
511 int msg_flags = CVAL(inbuf,1);
513 * We only really use 4 bytes of the outbuf, but for the smb_setlen
514 * calculation & friends (srv_send_smb uses that) we need the full smb
517 char outbuf[smb_size];
519 memset(outbuf, '\0', sizeof(outbuf));
521 smb_setlen(outbuf,0);
524 case NBSSrequest: /* session request */
526 /* inbuf_size is guarenteed to be at least 4. */
528 int name_type1, name_type2;
529 int name_len1, name_len2;
533 if (sconn->nbt.got_session) {
534 exit_server_cleanly("multiple session request not permitted");
537 SCVAL(outbuf,0,NBSSpositive);
540 /* inbuf_size is guaranteed to be at least 4. */
541 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
542 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
543 DEBUG(0,("Invalid name length in session request\n"));
544 reply_called_name_not_present(outbuf);
547 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
548 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
549 DEBUG(0,("Invalid name length in session request\n"));
550 reply_called_name_not_present(outbuf);
554 name_type1 = name_extract((unsigned char *)inbuf,
555 inbuf_size,(unsigned int)4,name1);
556 name_type2 = name_extract((unsigned char *)inbuf,
557 inbuf_size,(unsigned int)(4 + name_len1),name2);
559 if (name_type1 == -1 || name_type2 == -1) {
560 DEBUG(0,("Invalid name type in session request\n"));
561 reply_called_name_not_present(outbuf);
565 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
566 name1, name_type1, name2, name_type2));
568 if (netbios_session_retarget(sconn, name1, name_type1)) {
569 exit_server_cleanly("retargeted client");
573 * Windows NT/2k uses "*SMBSERVER" and XP uses
574 * "*SMBSERV" arrggg!!!
576 if (strequal(name1, "*SMBSERVER ")
577 || strequal(name1, "*SMBSERV ")) {
580 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
583 exit_server_cleanly("could not allocate raddr");
586 fstrcpy(name1, raddr);
589 set_local_machine_name(name1, True);
590 set_remote_machine_name(name2, True);
592 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
593 get_local_machine_name(), get_remote_machine_name(),
596 if (name_type2 == 'R') {
597 /* We are being asked for a pathworks session ---
599 reply_called_name_not_present(outbuf);
603 reload_services(sconn, conn_snum_used, true);
606 sconn->nbt.got_session = true;
610 case 0x89: /* session keepalive request
611 (some old clients produce this?) */
612 SCVAL(outbuf,0,NBSSkeepalive);
616 case NBSSpositive: /* positive session response */
617 case NBSSnegative: /* negative session response */
618 case NBSSretarget: /* retarget session response */
619 DEBUG(0,("Unexpected session response\n"));
622 case NBSSkeepalive: /* session keepalive */
627 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
628 msg_type, msg_flags));
630 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
632 if (CVAL(outbuf, 0) != 0x82) {
633 exit_server_cleanly("invalid netbios session");
638 /****************************************************************************
640 conn POINTER CAN BE NULL HERE !
641 ****************************************************************************/
643 void reply_tcon(struct smb_request *req)
645 connection_struct *conn = req->conn;
647 char *service_buf = NULL;
648 char *password = NULL;
653 TALLOC_CTX *ctx = talloc_tos();
654 struct smbd_server_connection *sconn = req->sconn;
656 START_PROFILE(SMBtcon);
658 if (req->buflen < 4) {
659 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
660 END_PROFILE(SMBtcon);
664 p = (const char *)req->buf + 1;
665 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
667 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
669 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
672 if (service_buf == NULL || password == NULL || dev == NULL) {
673 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
674 END_PROFILE(SMBtcon);
677 p = strrchr_m(service_buf,'\\');
681 service = service_buf;
684 conn = make_connection(sconn,service,dev,
685 req->vuid,&nt_status);
689 reply_nterror(req, nt_status);
690 END_PROFILE(SMBtcon);
694 reply_outbuf(req, 2, 0);
695 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
696 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
697 SSVAL(req->outbuf,smb_tid,conn->cnum);
699 DEBUG(3,("tcon service=%s cnum=%d\n",
700 service, conn->cnum));
702 END_PROFILE(SMBtcon);
706 /****************************************************************************
707 Reply to a tcon and X.
708 conn POINTER CAN BE NULL HERE !
709 ****************************************************************************/
711 void reply_tcon_and_X(struct smb_request *req)
713 connection_struct *conn = req->conn;
714 const char *service = NULL;
715 TALLOC_CTX *ctx = talloc_tos();
716 /* what the cleint thinks the device is */
717 char *client_devicetype = NULL;
718 /* what the server tells the client the share represents */
719 const char *server_devicetype;
725 struct smbd_server_connection *sconn = req->sconn;
727 START_PROFILE(SMBtconX);
730 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
731 END_PROFILE(SMBtconX);
735 passlen = SVAL(req->vwv+3, 0);
736 tcon_flags = SVAL(req->vwv+2, 0);
738 /* we might have to close an old one */
739 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
740 struct smbXsrv_tcon *tcon;
748 * TODO: cancel all outstanding requests on the tcon
750 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
751 if (!NT_STATUS_IS_OK(status)) {
752 DEBUG(0, ("reply_tcon_and_X: "
753 "smbXsrv_tcon_disconnect() failed: %s\n",
756 * If we hit this case, there is something completely
757 * wrong, so we better disconnect the transport connection.
759 END_PROFILE(SMBtconX);
760 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
767 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
768 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
769 END_PROFILE(SMBtconX);
773 if (sconn->smb1.negprot.encrypted_passwords) {
774 p = (const char *)req->buf + passlen;
776 p = (const char *)req->buf + passlen + 1;
779 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
783 END_PROFILE(SMBtconX);
788 * the service name can be either: \\server\share
789 * or share directly like on the DELL PowerVault 705
792 q = strchr_m(path+2,'\\');
794 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
795 END_PROFILE(SMBtconX);
803 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
804 &client_devicetype, p,
805 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
807 if (client_devicetype == NULL) {
808 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
809 END_PROFILE(SMBtconX);
813 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
815 conn = make_connection(sconn, service, client_devicetype,
816 req->vuid, &nt_status);
820 reply_nterror(req, nt_status);
821 END_PROFILE(SMBtconX);
826 server_devicetype = "IPC";
827 else if ( IS_PRINT(conn) )
828 server_devicetype = "LPT1:";
830 server_devicetype = "A:";
832 if (get_Protocol() < PROTOCOL_NT1) {
833 reply_outbuf(req, 2, 0);
834 if (message_push_string(&req->outbuf, server_devicetype,
835 STR_TERMINATE|STR_ASCII) == -1) {
836 reply_nterror(req, NT_STATUS_NO_MEMORY);
837 END_PROFILE(SMBtconX);
841 /* NT sets the fstype of IPC$ to the null string */
842 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(ctx, SNUM(conn));
843 uint16_t optional_support = 0;
845 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
846 /* Return permissions. */
850 reply_outbuf(req, 7, 0);
853 perm1 = FILE_ALL_ACCESS;
854 perm2 = FILE_ALL_ACCESS;
856 perm1 = conn->share_access;
859 SIVAL(req->outbuf, smb_vwv3, perm1);
860 SIVAL(req->outbuf, smb_vwv5, perm2);
862 reply_outbuf(req, 3, 0);
865 if ((message_push_string(&req->outbuf, server_devicetype,
866 STR_TERMINATE|STR_ASCII) == -1)
867 || (message_push_string(&req->outbuf, fstype,
868 STR_TERMINATE) == -1)) {
869 reply_nterror(req, NT_STATUS_NO_MEMORY);
870 END_PROFILE(SMBtconX);
874 /* what does setting this bit do? It is set by NT4 and
875 may affect the ability to autorun mounted cdroms */
876 optional_support |= SMB_SUPPORT_SEARCH_BITS;
878 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
880 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
881 DEBUG(2,("Serving %s as a Dfs root\n",
882 lp_servicename(ctx, SNUM(conn)) ));
883 optional_support |= SMB_SHARE_IN_DFS;
886 SSVAL(req->outbuf, smb_vwv2, optional_support);
889 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
890 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
892 DEBUG(3,("tconX service=%s \n",
895 /* set the incoming and outgoing tid to the just created one */
896 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
897 SSVAL(req->outbuf,smb_tid,conn->cnum);
899 END_PROFILE(SMBtconX);
901 req->tid = conn->cnum;
904 /****************************************************************************
905 Reply to an unknown type.
906 ****************************************************************************/
908 void reply_unknown_new(struct smb_request *req, uint8 type)
910 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
911 smb_fn_name(type), type, type));
912 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
916 /****************************************************************************
918 conn POINTER CAN BE NULL HERE !
919 ****************************************************************************/
921 void reply_ioctl(struct smb_request *req)
923 connection_struct *conn = req->conn;
930 START_PROFILE(SMBioctl);
933 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
934 END_PROFILE(SMBioctl);
938 device = SVAL(req->vwv+1, 0);
939 function = SVAL(req->vwv+2, 0);
940 ioctl_code = (device << 16) + function;
942 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
944 switch (ioctl_code) {
945 case IOCTL_QUERY_JOB_INFO:
949 reply_force_doserror(req, ERRSRV, ERRnosupport);
950 END_PROFILE(SMBioctl);
954 reply_outbuf(req, 8, replysize+1);
955 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
956 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
957 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
958 p = smb_buf(req->outbuf);
959 memset(p, '\0', replysize+1); /* valgrind-safe. */
960 p += 1; /* Allow for alignment */
962 switch (ioctl_code) {
963 case IOCTL_QUERY_JOB_INFO:
965 files_struct *fsp = file_fsp(
966 req, SVAL(req->vwv+0, 0));
968 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
969 END_PROFILE(SMBioctl);
973 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
975 srvstr_push((char *)req->outbuf, req->flags2, p+2,
976 lp_netbios_name(), 15,
977 STR_TERMINATE|STR_ASCII);
979 srvstr_push((char *)req->outbuf, req->flags2,
981 lp_servicename(talloc_tos(),
983 13, STR_TERMINATE|STR_ASCII);
991 END_PROFILE(SMBioctl);
995 /****************************************************************************
996 Strange checkpath NTSTATUS mapping.
997 ****************************************************************************/
999 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1001 /* Strange DOS error code semantics only for checkpath... */
1002 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1003 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1004 /* We need to map to ERRbadpath */
1005 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1011 /****************************************************************************
1012 Reply to a checkpath.
1013 ****************************************************************************/
1015 void reply_checkpath(struct smb_request *req)
1017 connection_struct *conn = req->conn;
1018 struct smb_filename *smb_fname = NULL;
1021 TALLOC_CTX *ctx = talloc_tos();
1023 START_PROFILE(SMBcheckpath);
1025 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1026 STR_TERMINATE, &status);
1028 if (!NT_STATUS_IS_OK(status)) {
1029 status = map_checkpath_error(req->flags2, status);
1030 reply_nterror(req, status);
1031 END_PROFILE(SMBcheckpath);
1035 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1037 status = filename_convert(ctx,
1039 req->flags2 & FLAGS2_DFS_PATHNAMES,
1045 if (!NT_STATUS_IS_OK(status)) {
1046 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1047 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1048 ERRSRV, ERRbadpath);
1049 END_PROFILE(SMBcheckpath);
1055 if (!VALID_STAT(smb_fname->st) &&
1056 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1057 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1058 smb_fname_str_dbg(smb_fname), strerror(errno)));
1059 status = map_nt_error_from_unix(errno);
1063 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1064 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1065 ERRDOS, ERRbadpath);
1069 reply_outbuf(req, 0, 0);
1072 /* We special case this - as when a Windows machine
1073 is parsing a path is steps through the components
1074 one at a time - if a component fails it expects
1075 ERRbadpath, not ERRbadfile.
1077 status = map_checkpath_error(req->flags2, status);
1078 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1080 * Windows returns different error codes if
1081 * the parent directory is valid but not the
1082 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1083 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1084 * if the path is invalid.
1086 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1087 ERRDOS, ERRbadpath);
1091 reply_nterror(req, status);
1094 TALLOC_FREE(smb_fname);
1095 END_PROFILE(SMBcheckpath);
1099 /****************************************************************************
1101 ****************************************************************************/
1103 void reply_getatr(struct smb_request *req)
1105 connection_struct *conn = req->conn;
1106 struct smb_filename *smb_fname = NULL;
1113 TALLOC_CTX *ctx = talloc_tos();
1114 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1116 START_PROFILE(SMBgetatr);
1118 p = (const char *)req->buf + 1;
1119 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1120 if (!NT_STATUS_IS_OK(status)) {
1121 reply_nterror(req, status);
1125 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1126 under WfWg - weird! */
1127 if (*fname == '\0') {
1128 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1129 if (!CAN_WRITE(conn)) {
1130 mode |= FILE_ATTRIBUTE_READONLY;
1135 status = filename_convert(ctx,
1137 req->flags2 & FLAGS2_DFS_PATHNAMES,
1142 if (!NT_STATUS_IS_OK(status)) {
1143 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1144 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1145 ERRSRV, ERRbadpath);
1148 reply_nterror(req, status);
1151 if (!VALID_STAT(smb_fname->st) &&
1152 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1153 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1154 smb_fname_str_dbg(smb_fname),
1156 reply_nterror(req, map_nt_error_from_unix(errno));
1160 mode = dos_mode(conn, smb_fname);
1161 size = smb_fname->st.st_ex_size;
1163 if (ask_sharemode) {
1164 struct timespec write_time_ts;
1165 struct file_id fileid;
1167 ZERO_STRUCT(write_time_ts);
1168 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1169 get_file_infos(fileid, 0, NULL, &write_time_ts);
1170 if (!null_timespec(write_time_ts)) {
1171 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1175 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1176 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1181 reply_outbuf(req, 10, 0);
1183 SSVAL(req->outbuf,smb_vwv0,mode);
1184 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1185 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1187 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1189 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1191 if (get_Protocol() >= PROTOCOL_NT1) {
1192 SSVAL(req->outbuf, smb_flg2,
1193 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1196 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1197 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1200 TALLOC_FREE(smb_fname);
1202 END_PROFILE(SMBgetatr);
1206 /****************************************************************************
1208 ****************************************************************************/
1210 void reply_setatr(struct smb_request *req)
1212 struct smb_file_time ft;
1213 connection_struct *conn = req->conn;
1214 struct smb_filename *smb_fname = NULL;
1220 TALLOC_CTX *ctx = talloc_tos();
1222 START_PROFILE(SMBsetatr);
1227 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1231 p = (const char *)req->buf + 1;
1232 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1233 if (!NT_STATUS_IS_OK(status)) {
1234 reply_nterror(req, status);
1238 status = filename_convert(ctx,
1240 req->flags2 & FLAGS2_DFS_PATHNAMES,
1245 if (!NT_STATUS_IS_OK(status)) {
1246 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1247 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1248 ERRSRV, ERRbadpath);
1251 reply_nterror(req, status);
1255 if (smb_fname->base_name[0] == '.' &&
1256 smb_fname->base_name[1] == '\0') {
1258 * Not sure here is the right place to catch this
1259 * condition. Might be moved to somewhere else later -- vl
1261 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1265 mode = SVAL(req->vwv+0, 0);
1266 mtime = srv_make_unix_date3(req->vwv+1);
1268 if (mode != FILE_ATTRIBUTE_NORMAL) {
1269 if (VALID_STAT_OF_DIR(smb_fname->st))
1270 mode |= FILE_ATTRIBUTE_DIRECTORY;
1272 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1274 status = check_access(conn, NULL, smb_fname,
1275 FILE_WRITE_ATTRIBUTES);
1276 if (!NT_STATUS_IS_OK(status)) {
1277 reply_nterror(req, status);
1281 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1283 reply_nterror(req, map_nt_error_from_unix(errno));
1288 ft.mtime = convert_time_t_to_timespec(mtime);
1289 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1290 if (!NT_STATUS_IS_OK(status)) {
1291 reply_nterror(req, status);
1295 reply_outbuf(req, 0, 0);
1297 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1300 TALLOC_FREE(smb_fname);
1301 END_PROFILE(SMBsetatr);
1305 /****************************************************************************
1307 ****************************************************************************/
1309 void reply_dskattr(struct smb_request *req)
1311 connection_struct *conn = req->conn;
1312 uint64_t dfree,dsize,bsize;
1313 START_PROFILE(SMBdskattr);
1315 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1316 reply_nterror(req, map_nt_error_from_unix(errno));
1317 END_PROFILE(SMBdskattr);
1321 reply_outbuf(req, 5, 0);
1323 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1324 double total_space, free_space;
1325 /* we need to scale this to a number that DOS6 can handle. We
1326 use floating point so we can handle large drives on systems
1327 that don't have 64 bit integers
1329 we end up displaying a maximum of 2G to DOS systems
1331 total_space = dsize * (double)bsize;
1332 free_space = dfree * (double)bsize;
1334 dsize = (uint64_t)((total_space+63*512) / (64*512));
1335 dfree = (uint64_t)((free_space+63*512) / (64*512));
1337 if (dsize > 0xFFFF) dsize = 0xFFFF;
1338 if (dfree > 0xFFFF) dfree = 0xFFFF;
1340 SSVAL(req->outbuf,smb_vwv0,dsize);
1341 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1342 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1343 SSVAL(req->outbuf,smb_vwv3,dfree);
1345 SSVAL(req->outbuf,smb_vwv0,dsize);
1346 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1347 SSVAL(req->outbuf,smb_vwv2,512);
1348 SSVAL(req->outbuf,smb_vwv3,dfree);
1351 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1353 END_PROFILE(SMBdskattr);
1358 * Utility function to split the filename from the directory.
1360 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1361 char **fname_dir_out,
1362 char **fname_mask_out)
1364 const char *p = NULL;
1365 char *fname_dir = NULL;
1366 char *fname_mask = NULL;
1368 p = strrchr_m(fname_in, '/');
1370 fname_dir = talloc_strdup(ctx, ".");
1371 fname_mask = talloc_strdup(ctx, fname_in);
1373 fname_dir = talloc_strndup(ctx, fname_in,
1374 PTR_DIFF(p, fname_in));
1375 fname_mask = talloc_strdup(ctx, p+1);
1378 if (!fname_dir || !fname_mask) {
1379 TALLOC_FREE(fname_dir);
1380 TALLOC_FREE(fname_mask);
1381 return NT_STATUS_NO_MEMORY;
1384 *fname_dir_out = fname_dir;
1385 *fname_mask_out = fname_mask;
1386 return NT_STATUS_OK;
1389 /****************************************************************************
1391 Can be called from SMBsearch, SMBffirst or SMBfunique.
1392 ****************************************************************************/
1394 void reply_search(struct smb_request *req)
1396 connection_struct *conn = req->conn;
1398 const char *mask = NULL;
1399 char *directory = NULL;
1400 struct smb_filename *smb_fname = NULL;
1404 struct timespec date;
1406 unsigned int numentries = 0;
1407 unsigned int maxentries = 0;
1408 bool finished = False;
1413 bool check_descend = False;
1414 bool expect_close = False;
1416 bool mask_contains_wcard = False;
1417 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1418 TALLOC_CTX *ctx = talloc_tos();
1419 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1420 struct dptr_struct *dirptr = NULL;
1421 struct smbd_server_connection *sconn = req->sconn;
1423 START_PROFILE(SMBsearch);
1426 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1430 if (lp_posix_pathnames()) {
1431 reply_unknown_new(req, req->cmd);
1435 /* If we were called as SMBffirst then we must expect close. */
1436 if(req->cmd == SMBffirst) {
1437 expect_close = True;
1440 reply_outbuf(req, 1, 3);
1441 maxentries = SVAL(req->vwv+0, 0);
1442 dirtype = SVAL(req->vwv+1, 0);
1443 p = (const char *)req->buf + 1;
1444 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1445 &nt_status, &mask_contains_wcard);
1446 if (!NT_STATUS_IS_OK(nt_status)) {
1447 reply_nterror(req, nt_status);
1452 status_len = SVAL(p, 0);
1455 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1457 if (status_len == 0) {
1458 nt_status = filename_convert(ctx, conn,
1459 req->flags2 & FLAGS2_DFS_PATHNAMES,
1461 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1462 &mask_contains_wcard,
1464 if (!NT_STATUS_IS_OK(nt_status)) {
1465 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1466 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1467 ERRSRV, ERRbadpath);
1470 reply_nterror(req, nt_status);
1474 directory = smb_fname->base_name;
1476 p = strrchr_m(directory,'/');
1477 if ((p != NULL) && (*directory != '/')) {
1479 directory = talloc_strndup(ctx, directory,
1480 PTR_DIFF(p, directory));
1483 directory = talloc_strdup(ctx,".");
1487 reply_nterror(req, NT_STATUS_NO_MEMORY);
1491 memset((char *)status,'\0',21);
1492 SCVAL(status,0,(dirtype & 0x1F));
1494 nt_status = dptr_create(conn,
1502 mask_contains_wcard,
1505 if (!NT_STATUS_IS_OK(nt_status)) {
1506 reply_nterror(req, nt_status);
1509 dptr_num = dptr_dnum(dirptr);
1512 const char *dirpath;
1514 memcpy(status,p,21);
1515 status_dirtype = CVAL(status,0) & 0x1F;
1516 if (status_dirtype != (dirtype & 0x1F)) {
1517 dirtype = status_dirtype;
1520 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1524 dirpath = dptr_path(sconn, dptr_num);
1525 directory = talloc_strdup(ctx, dirpath);
1527 reply_nterror(req, NT_STATUS_NO_MEMORY);
1531 mask = dptr_wcard(sconn, dptr_num);
1536 * For a 'continue' search we have no string. So
1537 * check from the initial saved string.
1539 mask_contains_wcard = ms_has_wild(mask);
1540 dirtype = dptr_attr(sconn, dptr_num);
1543 DEBUG(4,("dptr_num is %d\n",dptr_num));
1545 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1546 dptr_init_search_op(dirptr);
1548 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1549 char buf[DIR_STRUCT_SIZE];
1550 memcpy(buf,status,21);
1551 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1552 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1553 reply_nterror(req, NT_STATUS_NO_MEMORY);
1556 dptr_fill(sconn, buf+12,dptr_num);
1557 if (dptr_zero(buf+12) && (status_len==0)) {
1562 if (message_push_blob(&req->outbuf,
1563 data_blob_const(buf, sizeof(buf)))
1565 reply_nterror(req, NT_STATUS_NO_MEMORY);
1573 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1576 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1577 directory,lp_dontdescend(ctx, SNUM(conn))));
1578 if (in_list(directory, lp_dontdescend(ctx, SNUM(conn)),True)) {
1579 check_descend = True;
1582 for (i=numentries;(i<maxentries) && !finished;i++) {
1583 finished = !get_dir_entry(ctx,
1594 char buf[DIR_STRUCT_SIZE];
1595 memcpy(buf,status,21);
1596 if (!make_dir_struct(ctx,
1602 convert_timespec_to_time_t(date),
1603 !allow_long_path_components)) {
1604 reply_nterror(req, NT_STATUS_NO_MEMORY);
1607 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1610 if (message_push_blob(&req->outbuf,
1611 data_blob_const(buf, sizeof(buf)))
1613 reply_nterror(req, NT_STATUS_NO_MEMORY);
1623 /* If we were called as SMBffirst with smb_search_id == NULL
1624 and no entries were found then return error and close dirptr
1627 if (numentries == 0) {
1628 dptr_close(sconn, &dptr_num);
1629 } else if(expect_close && status_len == 0) {
1630 /* Close the dptr - we know it's gone */
1631 dptr_close(sconn, &dptr_num);
1634 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1635 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1636 dptr_close(sconn, &dptr_num);
1639 if ((numentries == 0) && !mask_contains_wcard) {
1640 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1644 SSVAL(req->outbuf,smb_vwv0,numentries);
1645 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1646 SCVAL(smb_buf(req->outbuf),0,5);
1647 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1649 /* The replies here are never long name. */
1650 SSVAL(req->outbuf, smb_flg2,
1651 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1652 if (!allow_long_path_components) {
1653 SSVAL(req->outbuf, smb_flg2,
1654 SVAL(req->outbuf, smb_flg2)
1655 & (~FLAGS2_LONG_PATH_COMPONENTS));
1658 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1659 SSVAL(req->outbuf, smb_flg2,
1660 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1662 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1663 smb_fn_name(req->cmd),
1670 TALLOC_FREE(directory);
1671 TALLOC_FREE(smb_fname);
1672 END_PROFILE(SMBsearch);
1676 /****************************************************************************
1677 Reply to a fclose (stop directory search).
1678 ****************************************************************************/
1680 void reply_fclose(struct smb_request *req)
1688 bool path_contains_wcard = False;
1689 TALLOC_CTX *ctx = talloc_tos();
1690 struct smbd_server_connection *sconn = req->sconn;
1692 START_PROFILE(SMBfclose);
1694 if (lp_posix_pathnames()) {
1695 reply_unknown_new(req, req->cmd);
1696 END_PROFILE(SMBfclose);
1700 p = (const char *)req->buf + 1;
1701 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1702 &err, &path_contains_wcard);
1703 if (!NT_STATUS_IS_OK(err)) {
1704 reply_nterror(req, err);
1705 END_PROFILE(SMBfclose);
1709 status_len = SVAL(p,0);
1712 if (status_len == 0) {
1713 reply_force_doserror(req, ERRSRV, ERRsrverror);
1714 END_PROFILE(SMBfclose);
1718 memcpy(status,p,21);
1720 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1721 /* Close the dptr - we know it's gone */
1722 dptr_close(sconn, &dptr_num);
1725 reply_outbuf(req, 1, 0);
1726 SSVAL(req->outbuf,smb_vwv0,0);
1728 DEBUG(3,("search close\n"));
1730 END_PROFILE(SMBfclose);
1734 /****************************************************************************
1736 ****************************************************************************/
1738 void reply_open(struct smb_request *req)
1740 connection_struct *conn = req->conn;
1741 struct smb_filename *smb_fname = NULL;
1753 uint32 create_disposition;
1754 uint32 create_options = 0;
1755 uint32_t private_flags = 0;
1757 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1758 TALLOC_CTX *ctx = talloc_tos();
1760 START_PROFILE(SMBopen);
1763 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1767 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1768 deny_mode = SVAL(req->vwv+0, 0);
1769 dos_attr = SVAL(req->vwv+1, 0);
1771 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1772 STR_TERMINATE, &status);
1773 if (!NT_STATUS_IS_OK(status)) {
1774 reply_nterror(req, status);
1778 status = filename_convert(ctx,
1780 req->flags2 & FLAGS2_DFS_PATHNAMES,
1785 if (!NT_STATUS_IS_OK(status)) {
1786 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1787 reply_botherror(req,
1788 NT_STATUS_PATH_NOT_COVERED,
1789 ERRSRV, ERRbadpath);
1792 reply_nterror(req, status);
1796 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1797 OPENX_FILE_EXISTS_OPEN, &access_mask,
1798 &share_mode, &create_disposition,
1799 &create_options, &private_flags)) {
1800 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1804 status = SMB_VFS_CREATE_FILE(
1807 0, /* root_dir_fid */
1808 smb_fname, /* fname */
1809 access_mask, /* access_mask */
1810 share_mode, /* share_access */
1811 create_disposition, /* create_disposition*/
1812 create_options, /* create_options */
1813 dos_attr, /* file_attributes */
1814 oplock_request, /* oplock_request */
1815 0, /* allocation_size */
1822 if (!NT_STATUS_IS_OK(status)) {
1823 if (open_was_deferred(req->sconn, req->mid)) {
1824 /* We have re-scheduled this call. */
1827 reply_openerror(req, status);
1831 size = smb_fname->st.st_ex_size;
1832 fattr = dos_mode(conn, smb_fname);
1834 /* Deal with other possible opens having a modified
1836 if (ask_sharemode) {
1837 struct timespec write_time_ts;
1839 ZERO_STRUCT(write_time_ts);
1840 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1841 if (!null_timespec(write_time_ts)) {
1842 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1846 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1848 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1849 DEBUG(3,("attempt to open a directory %s\n",
1851 close_file(req, fsp, ERROR_CLOSE);
1852 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1853 ERRDOS, ERRnoaccess);
1857 reply_outbuf(req, 7, 0);
1858 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1859 SSVAL(req->outbuf,smb_vwv1,fattr);
1860 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1861 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1863 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1865 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1866 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1868 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1869 SCVAL(req->outbuf,smb_flg,
1870 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1873 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1874 SCVAL(req->outbuf,smb_flg,
1875 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1878 TALLOC_FREE(smb_fname);
1879 END_PROFILE(SMBopen);
1883 /****************************************************************************
1884 Reply to an open and X.
1885 ****************************************************************************/
1887 void reply_open_and_X(struct smb_request *req)
1889 connection_struct *conn = req->conn;
1890 struct smb_filename *smb_fname = NULL;
1895 /* Breakout the oplock request bits so we can set the
1896 reply bits separately. */
1897 int ex_oplock_request;
1898 int core_oplock_request;
1901 int smb_sattr = SVAL(req->vwv+4, 0);
1902 uint32 smb_time = make_unix_date3(req->vwv+6);
1910 uint64_t allocation_size;
1911 ssize_t retval = -1;
1914 uint32 create_disposition;
1915 uint32 create_options = 0;
1916 uint32_t private_flags = 0;
1917 TALLOC_CTX *ctx = talloc_tos();
1919 START_PROFILE(SMBopenX);
1921 if (req->wct < 15) {
1922 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1926 open_flags = SVAL(req->vwv+2, 0);
1927 deny_mode = SVAL(req->vwv+3, 0);
1928 smb_attr = SVAL(req->vwv+5, 0);
1929 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1930 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1931 oplock_request = ex_oplock_request | core_oplock_request;
1932 smb_ofun = SVAL(req->vwv+8, 0);
1933 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1935 /* If it's an IPC, pass off the pipe handler. */
1937 if (lp_nt_pipe_support()) {
1938 reply_open_pipe_and_X(conn, req);
1940 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1945 /* XXXX we need to handle passed times, sattr and flags */
1946 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1947 STR_TERMINATE, &status);
1948 if (!NT_STATUS_IS_OK(status)) {
1949 reply_nterror(req, status);
1953 status = filename_convert(ctx,
1955 req->flags2 & FLAGS2_DFS_PATHNAMES,
1960 if (!NT_STATUS_IS_OK(status)) {
1961 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1962 reply_botherror(req,
1963 NT_STATUS_PATH_NOT_COVERED,
1964 ERRSRV, ERRbadpath);
1967 reply_nterror(req, status);
1971 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1973 &access_mask, &share_mode,
1974 &create_disposition,
1977 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1981 status = SMB_VFS_CREATE_FILE(
1984 0, /* root_dir_fid */
1985 smb_fname, /* fname */
1986 access_mask, /* access_mask */
1987 share_mode, /* share_access */
1988 create_disposition, /* create_disposition*/
1989 create_options, /* create_options */
1990 smb_attr, /* file_attributes */
1991 oplock_request, /* oplock_request */
1992 0, /* allocation_size */
1997 &smb_action); /* pinfo */
1999 if (!NT_STATUS_IS_OK(status)) {
2000 if (open_was_deferred(req->sconn, req->mid)) {
2001 /* We have re-scheduled this call. */
2004 reply_openerror(req, status);
2008 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2009 if the file is truncated or created. */
2010 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2011 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2012 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2013 close_file(req, fsp, ERROR_CLOSE);
2014 reply_nterror(req, NT_STATUS_DISK_FULL);
2017 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2019 close_file(req, fsp, ERROR_CLOSE);
2020 reply_nterror(req, NT_STATUS_DISK_FULL);
2023 status = vfs_stat_fsp(fsp);
2024 if (!NT_STATUS_IS_OK(status)) {
2025 close_file(req, fsp, ERROR_CLOSE);
2026 reply_nterror(req, status);
2031 fattr = dos_mode(conn, fsp->fsp_name);
2032 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2033 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2034 close_file(req, fsp, ERROR_CLOSE);
2035 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2039 /* If the caller set the extended oplock request bit
2040 and we granted one (by whatever means) - set the
2041 correct bit for extended oplock reply.
2044 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2045 smb_action |= EXTENDED_OPLOCK_GRANTED;
2048 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2049 smb_action |= EXTENDED_OPLOCK_GRANTED;
2052 /* If the caller set the core oplock request bit
2053 and we granted one (by whatever means) - set the
2054 correct bit for core oplock reply.
2057 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2058 reply_outbuf(req, 19, 0);
2060 reply_outbuf(req, 15, 0);
2063 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2064 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2066 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2067 SCVAL(req->outbuf, smb_flg,
2068 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2071 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2072 SCVAL(req->outbuf, smb_flg,
2073 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2076 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2077 SSVAL(req->outbuf,smb_vwv3,fattr);
2078 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2079 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2081 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2083 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2084 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2085 SSVAL(req->outbuf,smb_vwv11,smb_action);
2087 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2088 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2092 TALLOC_FREE(smb_fname);
2093 END_PROFILE(SMBopenX);
2097 /****************************************************************************
2098 Reply to a SMBulogoffX.
2099 ****************************************************************************/
2101 void reply_ulogoffX(struct smb_request *req)
2103 struct smbd_server_connection *sconn = req->sconn;
2104 struct user_struct *vuser;
2105 struct smbXsrv_session *session = NULL;
2108 START_PROFILE(SMBulogoffX);
2110 vuser = get_valid_user_struct(sconn, req->vuid);
2113 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2114 (unsigned long long)req->vuid));
2116 req->vuid = UID_FIELD_INVALID;
2117 reply_force_doserror(req, ERRSRV, ERRbaduid);
2118 END_PROFILE(SMBulogoffX);
2122 session = vuser->session;
2126 * TODO: cancel all outstanding requests on the session
2128 status = smbXsrv_session_logoff(session);
2129 if (!NT_STATUS_IS_OK(status)) {
2130 DEBUG(0, ("reply_ulogoff: "
2131 "smbXsrv_session_logoff() failed: %s\n",
2132 nt_errstr(status)));
2134 * If we hit this case, there is something completely
2135 * wrong, so we better disconnect the transport connection.
2137 END_PROFILE(SMBulogoffX);
2138 exit_server(__location__ ": smbXsrv_session_logoff failed");
2142 TALLOC_FREE(session);
2144 reply_outbuf(req, 2, 0);
2145 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2146 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2148 DEBUG(3, ("ulogoffX vuid=%llu\n",
2149 (unsigned long long)req->vuid));
2151 END_PROFILE(SMBulogoffX);
2152 req->vuid = UID_FIELD_INVALID;
2155 /****************************************************************************
2156 Reply to a mknew or a create.
2157 ****************************************************************************/
2159 void reply_mknew(struct smb_request *req)
2161 connection_struct *conn = req->conn;
2162 struct smb_filename *smb_fname = NULL;
2165 struct smb_file_time ft;
2167 int oplock_request = 0;
2169 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2170 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2171 uint32 create_disposition;
2172 uint32 create_options = 0;
2173 TALLOC_CTX *ctx = talloc_tos();
2175 START_PROFILE(SMBcreate);
2179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2183 fattr = SVAL(req->vwv+0, 0);
2184 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2187 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2189 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2190 STR_TERMINATE, &status);
2191 if (!NT_STATUS_IS_OK(status)) {
2192 reply_nterror(req, status);
2196 status = filename_convert(ctx,
2198 req->flags2 & FLAGS2_DFS_PATHNAMES,
2203 if (!NT_STATUS_IS_OK(status)) {
2204 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2205 reply_botherror(req,
2206 NT_STATUS_PATH_NOT_COVERED,
2207 ERRSRV, ERRbadpath);
2210 reply_nterror(req, status);
2214 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2215 DEBUG(0,("Attempt to create file (%s) with volid set - "
2216 "please report this\n",
2217 smb_fname_str_dbg(smb_fname)));
2220 if(req->cmd == SMBmknew) {
2221 /* We should fail if file exists. */
2222 create_disposition = FILE_CREATE;
2224 /* Create if file doesn't exist, truncate if it does. */
2225 create_disposition = FILE_OVERWRITE_IF;
2228 status = SMB_VFS_CREATE_FILE(
2231 0, /* root_dir_fid */
2232 smb_fname, /* fname */
2233 access_mask, /* access_mask */
2234 share_mode, /* share_access */
2235 create_disposition, /* create_disposition*/
2236 create_options, /* create_options */
2237 fattr, /* file_attributes */
2238 oplock_request, /* oplock_request */
2239 0, /* allocation_size */
2240 0, /* private_flags */
2246 if (!NT_STATUS_IS_OK(status)) {
2247 if (open_was_deferred(req->sconn, req->mid)) {
2248 /* We have re-scheduled this call. */
2251 reply_openerror(req, status);
2255 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2256 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2257 if (!NT_STATUS_IS_OK(status)) {
2258 END_PROFILE(SMBcreate);
2262 reply_outbuf(req, 1, 0);
2263 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2265 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2266 SCVAL(req->outbuf,smb_flg,
2267 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2270 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2271 SCVAL(req->outbuf,smb_flg,
2272 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2275 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2276 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2277 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2278 (unsigned int)fattr));
2281 TALLOC_FREE(smb_fname);
2282 END_PROFILE(SMBcreate);
2286 /****************************************************************************
2287 Reply to a create temporary file.
2288 ****************************************************************************/
2290 void reply_ctemp(struct smb_request *req)
2292 connection_struct *conn = req->conn;
2293 struct smb_filename *smb_fname = NULL;
2301 TALLOC_CTX *ctx = talloc_tos();
2303 START_PROFILE(SMBctemp);
2306 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2310 fattr = SVAL(req->vwv+0, 0);
2311 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2313 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2314 STR_TERMINATE, &status);
2315 if (!NT_STATUS_IS_OK(status)) {
2316 reply_nterror(req, status);
2320 fname = talloc_asprintf(ctx,
2324 fname = talloc_strdup(ctx, "TMXXXXXX");
2328 reply_nterror(req, NT_STATUS_NO_MEMORY);
2332 status = filename_convert(ctx, conn,
2333 req->flags2 & FLAGS2_DFS_PATHNAMES,
2338 if (!NT_STATUS_IS_OK(status)) {
2339 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2340 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2341 ERRSRV, ERRbadpath);
2344 reply_nterror(req, status);
2348 tmpfd = mkstemp(smb_fname->base_name);
2350 reply_nterror(req, map_nt_error_from_unix(errno));
2354 SMB_VFS_STAT(conn, smb_fname);
2356 /* We should fail if file does not exist. */
2357 status = SMB_VFS_CREATE_FILE(
2360 0, /* root_dir_fid */
2361 smb_fname, /* fname */
2362 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2363 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2364 FILE_OPEN, /* create_disposition*/
2365 0, /* create_options */
2366 fattr, /* file_attributes */
2367 oplock_request, /* oplock_request */
2368 0, /* allocation_size */
2369 0, /* private_flags */
2375 /* close fd from mkstemp() */
2378 if (!NT_STATUS_IS_OK(status)) {
2379 if (open_was_deferred(req->sconn, req->mid)) {
2380 /* We have re-scheduled this call. */
2383 reply_openerror(req, status);
2387 reply_outbuf(req, 1, 0);
2388 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2390 /* the returned filename is relative to the directory */
2391 s = strrchr_m(fsp->fsp_name->base_name, '/');
2393 s = fsp->fsp_name->base_name;
2399 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2400 thing in the byte section. JRA */
2401 SSVALS(p, 0, -1); /* what is this? not in spec */
2403 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2405 reply_nterror(req, NT_STATUS_NO_MEMORY);
2409 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2410 SCVAL(req->outbuf, smb_flg,
2411 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2414 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2415 SCVAL(req->outbuf, smb_flg,
2416 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2419 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2420 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2421 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2423 TALLOC_FREE(smb_fname);
2424 END_PROFILE(SMBctemp);
2428 /*******************************************************************
2429 Check if a user is allowed to rename a file.
2430 ********************************************************************/
2432 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2435 if (!CAN_WRITE(conn)) {
2436 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2439 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2440 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2441 /* Only bother to read the DOS attribute if we might deny the
2442 rename on the grounds of attribute missmatch. */
2443 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2444 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2445 return NT_STATUS_NO_SUCH_FILE;
2449 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2450 if (fsp->posix_open) {
2451 return NT_STATUS_OK;
2454 /* If no pathnames are open below this
2455 directory, allow the rename. */
2457 if (file_find_subpath(fsp)) {
2458 return NT_STATUS_ACCESS_DENIED;
2460 return NT_STATUS_OK;
2463 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2464 return NT_STATUS_OK;
2467 return NT_STATUS_ACCESS_DENIED;
2470 /*******************************************************************
2471 * unlink a file with all relevant access checks
2472 *******************************************************************/
2474 static NTSTATUS do_unlink(connection_struct *conn,
2475 struct smb_request *req,
2476 struct smb_filename *smb_fname,
2481 uint32 dirtype_orig = dirtype;
2484 bool posix_paths = lp_posix_pathnames();
2486 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2487 smb_fname_str_dbg(smb_fname),
2490 if (!CAN_WRITE(conn)) {
2491 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2495 ret = SMB_VFS_LSTAT(conn, smb_fname);
2497 ret = SMB_VFS_STAT(conn, smb_fname);
2500 return map_nt_error_from_unix(errno);
2503 fattr = dos_mode(conn, smb_fname);
2505 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2506 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2509 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2511 return NT_STATUS_NO_SUCH_FILE;
2514 if (!dir_check_ftype(conn, fattr, dirtype)) {
2515 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2516 return NT_STATUS_FILE_IS_A_DIRECTORY;
2518 return NT_STATUS_NO_SUCH_FILE;
2521 if (dirtype_orig & 0x8000) {
2522 /* These will never be set for POSIX. */
2523 return NT_STATUS_NO_SUCH_FILE;
2527 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2528 return NT_STATUS_FILE_IS_A_DIRECTORY;
2531 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2532 return NT_STATUS_NO_SUCH_FILE;
2535 if (dirtype & 0xFF00) {
2536 /* These will never be set for POSIX. */
2537 return NT_STATUS_NO_SUCH_FILE;
2542 return NT_STATUS_NO_SUCH_FILE;
2545 /* Can't delete a directory. */
2546 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2547 return NT_STATUS_FILE_IS_A_DIRECTORY;
2552 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2553 return NT_STATUS_OBJECT_NAME_INVALID;
2554 #endif /* JRATEST */
2556 /* On open checks the open itself will check the share mode, so
2557 don't do it here as we'll get it wrong. */
2559 status = SMB_VFS_CREATE_FILE
2562 0, /* root_dir_fid */
2563 smb_fname, /* fname */
2564 DELETE_ACCESS, /* access_mask */
2565 FILE_SHARE_NONE, /* share_access */
2566 FILE_OPEN, /* create_disposition*/
2567 FILE_NON_DIRECTORY_FILE, /* create_options */
2568 /* file_attributes */
2569 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2570 FILE_ATTRIBUTE_NORMAL,
2571 0, /* oplock_request */
2572 0, /* allocation_size */
2573 0, /* private_flags */
2579 if (!NT_STATUS_IS_OK(status)) {
2580 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2581 nt_errstr(status)));
2585 status = can_set_delete_on_close(fsp, fattr);
2586 if (!NT_STATUS_IS_OK(status)) {
2587 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2589 smb_fname_str_dbg(smb_fname),
2590 nt_errstr(status)));
2591 close_file(req, fsp, NORMAL_CLOSE);
2595 /* The set is across all open files on this dev/inode pair. */
2596 if (!set_delete_on_close(fsp, True,
2597 conn->session_info->security_token,
2598 conn->session_info->unix_token)) {
2599 close_file(req, fsp, NORMAL_CLOSE);
2600 return NT_STATUS_ACCESS_DENIED;
2603 return close_file(req, fsp, NORMAL_CLOSE);
2606 /****************************************************************************
2607 The guts of the unlink command, split out so it may be called by the NT SMB
2609 ****************************************************************************/
2611 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2612 uint32 dirtype, struct smb_filename *smb_fname,
2615 char *fname_dir = NULL;
2616 char *fname_mask = NULL;
2618 NTSTATUS status = NT_STATUS_OK;
2619 TALLOC_CTX *ctx = talloc_tos();
2621 /* Split up the directory from the filename/mask. */
2622 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2623 &fname_dir, &fname_mask);
2624 if (!NT_STATUS_IS_OK(status)) {
2629 * We should only check the mangled cache
2630 * here if unix_convert failed. This means
2631 * that the path in 'mask' doesn't exist
2632 * on the file system and so we need to look
2633 * for a possible mangle. This patch from
2634 * Tine Smukavec <valentin.smukavec@hermes.si>.
2637 if (!VALID_STAT(smb_fname->st) &&
2638 mangle_is_mangled(fname_mask, conn->params)) {
2639 char *new_mask = NULL;
2640 mangle_lookup_name_from_8_3(ctx, fname_mask,
2641 &new_mask, conn->params);
2643 TALLOC_FREE(fname_mask);
2644 fname_mask = new_mask;
2651 * Only one file needs to be unlinked. Append the mask back
2652 * onto the directory.
2654 TALLOC_FREE(smb_fname->base_name);
2655 if (ISDOT(fname_dir)) {
2656 /* Ensure we use canonical names on open. */
2657 smb_fname->base_name = talloc_asprintf(smb_fname,
2661 smb_fname->base_name = talloc_asprintf(smb_fname,
2666 if (!smb_fname->base_name) {
2667 status = NT_STATUS_NO_MEMORY;
2671 dirtype = FILE_ATTRIBUTE_NORMAL;
2674 status = check_name(conn, smb_fname->base_name);
2675 if (!NT_STATUS_IS_OK(status)) {
2679 status = do_unlink(conn, req, smb_fname, dirtype);
2680 if (!NT_STATUS_IS_OK(status)) {
2686 struct smb_Dir *dir_hnd = NULL;
2688 const char *dname = NULL;
2689 char *talloced = NULL;
2691 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2692 status = NT_STATUS_OBJECT_NAME_INVALID;
2696 if (strequal(fname_mask,"????????.???")) {
2697 TALLOC_FREE(fname_mask);
2698 fname_mask = talloc_strdup(ctx, "*");
2700 status = NT_STATUS_NO_MEMORY;
2705 status = check_name(conn, fname_dir);
2706 if (!NT_STATUS_IS_OK(status)) {
2710 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2712 if (dir_hnd == NULL) {
2713 status = map_nt_error_from_unix(errno);
2717 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2718 the pattern matches against the long name, otherwise the short name
2719 We don't implement this yet XXXX
2722 status = NT_STATUS_NO_SUCH_FILE;
2724 while ((dname = ReadDirName(dir_hnd, &offset,
2725 &smb_fname->st, &talloced))) {
2726 TALLOC_CTX *frame = talloc_stackframe();
2728 if (!is_visible_file(conn, fname_dir, dname,
2729 &smb_fname->st, true)) {
2731 TALLOC_FREE(talloced);
2735 /* Quick check for "." and ".." */
2736 if (ISDOT(dname) || ISDOTDOT(dname)) {
2738 TALLOC_FREE(talloced);
2742 if(!mask_match(dname, fname_mask,
2743 conn->case_sensitive)) {
2745 TALLOC_FREE(talloced);
2749 TALLOC_FREE(smb_fname->base_name);
2750 if (ISDOT(fname_dir)) {
2751 /* Ensure we use canonical names on open. */
2752 smb_fname->base_name =
2753 talloc_asprintf(smb_fname, "%s",
2756 smb_fname->base_name =
2757 talloc_asprintf(smb_fname, "%s/%s",
2761 if (!smb_fname->base_name) {
2762 TALLOC_FREE(dir_hnd);
2763 status = NT_STATUS_NO_MEMORY;
2765 TALLOC_FREE(talloced);
2769 status = check_name(conn, smb_fname->base_name);
2770 if (!NT_STATUS_IS_OK(status)) {
2771 TALLOC_FREE(dir_hnd);
2773 TALLOC_FREE(talloced);
2777 status = do_unlink(conn, req, smb_fname, dirtype);
2778 if (!NT_STATUS_IS_OK(status)) {
2780 TALLOC_FREE(talloced);
2785 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2786 smb_fname->base_name));
2789 TALLOC_FREE(talloced);
2791 TALLOC_FREE(dir_hnd);
2794 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2795 status = map_nt_error_from_unix(errno);
2799 TALLOC_FREE(fname_dir);
2800 TALLOC_FREE(fname_mask);
2804 /****************************************************************************
2806 ****************************************************************************/
2808 void reply_unlink(struct smb_request *req)
2810 connection_struct *conn = req->conn;
2812 struct smb_filename *smb_fname = NULL;
2815 bool path_contains_wcard = False;
2816 TALLOC_CTX *ctx = talloc_tos();
2818 START_PROFILE(SMBunlink);
2821 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2825 dirtype = SVAL(req->vwv+0, 0);
2827 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2828 STR_TERMINATE, &status,
2829 &path_contains_wcard);
2830 if (!NT_STATUS_IS_OK(status)) {
2831 reply_nterror(req, status);
2835 status = filename_convert(ctx, conn,
2836 req->flags2 & FLAGS2_DFS_PATHNAMES,
2838 UCF_COND_ALLOW_WCARD_LCOMP,
2839 &path_contains_wcard,
2841 if (!NT_STATUS_IS_OK(status)) {
2842 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2843 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2844 ERRSRV, ERRbadpath);
2847 reply_nterror(req, status);
2851 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2853 status = unlink_internals(conn, req, dirtype, smb_fname,
2854 path_contains_wcard);
2855 if (!NT_STATUS_IS_OK(status)) {
2856 if (open_was_deferred(req->sconn, req->mid)) {
2857 /* We have re-scheduled this call. */
2860 reply_nterror(req, status);
2864 reply_outbuf(req, 0, 0);
2866 TALLOC_FREE(smb_fname);
2867 END_PROFILE(SMBunlink);
2871 /****************************************************************************
2873 ****************************************************************************/
2875 static void fail_readraw(void)
2877 const char *errstr = talloc_asprintf(talloc_tos(),
2878 "FAIL ! reply_readbraw: socket write fail (%s)",
2883 exit_server_cleanly(errstr);
2886 /****************************************************************************
2887 Fake (read/write) sendfile. Returns -1 on read or write fail.
2888 ****************************************************************************/
2890 ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread)
2893 size_t tosend = nread;
2900 bufsize = MIN(nread, 65536);
2902 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2906 while (tosend > 0) {
2910 if (tosend > bufsize) {
2915 ret = read_file(fsp,buf,startpos,cur_read);
2921 /* If we had a short read, fill with zeros. */
2922 if (ret < cur_read) {
2923 memset(buf + ret, '\0', cur_read - ret);
2926 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2928 char addr[INET6_ADDRSTRLEN];
2930 * Try and give an error message saying what
2933 DEBUG(0, ("write_data failed for client %s. "
2935 get_peer_addr(fsp->conn->sconn->sock, addr,
2942 startpos += cur_read;
2946 return (ssize_t)nread;
2949 /****************************************************************************
2950 Deal with the case of sendfile reading less bytes from the file than
2951 requested. Fill with zeros (all we can do).
2952 ****************************************************************************/
2954 void sendfile_short_send(files_struct *fsp,
2959 #define SHORT_SEND_BUFSIZE 1024
2960 if (nread < headersize) {
2961 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2962 "header for file %s (%s). Terminating\n",
2963 fsp_str_dbg(fsp), strerror(errno)));
2964 exit_server_cleanly("sendfile_short_send failed");
2967 nread -= headersize;
2969 if (nread < smb_maxcnt) {
2970 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2972 exit_server_cleanly("sendfile_short_send: "
2976 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2977 "with zeros !\n", fsp_str_dbg(fsp)));
2979 while (nread < smb_maxcnt) {
2981 * We asked for the real file size and told sendfile
2982 * to not go beyond the end of the file. But it can
2983 * happen that in between our fstat call and the
2984 * sendfile call the file was truncated. This is very
2985 * bad because we have already announced the larger
2986 * number of bytes to the client.
2988 * The best we can do now is to send 0-bytes, just as
2989 * a read from a hole in a sparse file would do.
2991 * This should happen rarely enough that I don't care
2992 * about efficiency here :-)
2996 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2997 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2999 char addr[INET6_ADDRSTRLEN];
3001 * Try and give an error message saying what
3004 DEBUG(0, ("write_data failed for client %s. "
3007 fsp->conn->sconn->sock, addr,
3010 exit_server_cleanly("sendfile_short_send: "
3011 "write_data failed");
3019 /****************************************************************************
3020 Return a readbraw error (4 bytes of zero).
3021 ****************************************************************************/
3023 static void reply_readbraw_error(struct smbd_server_connection *sconn)
3029 smbd_lock_socket(sconn);
3030 if (write_data(sconn->sock,header,4) != 4) {
3031 char addr[INET6_ADDRSTRLEN];
3033 * Try and give an error message saying what
3036 DEBUG(0, ("write_data failed for client %s. "
3038 get_peer_addr(sconn->sock, addr, sizeof(addr)),
3043 smbd_unlock_socket(sconn);
3046 /****************************************************************************
3047 Use sendfile in readbraw.
3048 ****************************************************************************/
3050 static void send_file_readbraw(connection_struct *conn,
3051 struct smb_request *req,
3057 struct smbd_server_connection *sconn = req->sconn;
3058 char *outbuf = NULL;
3062 * We can only use sendfile on a non-chained packet
3063 * but we can use on a non-oplocked file. tridge proved this
3064 * on a train in Germany :-). JRA.
3065 * reply_readbraw has already checked the length.
3068 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3069 (fsp->wcp == NULL) &&
3070 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3071 ssize_t sendfile_read = -1;
3073 DATA_BLOB header_blob;
3075 _smb_setlen(header,nread);
3076 header_blob = data_blob_const(header, 4);
3078 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3079 &header_blob, startpos,
3081 if (sendfile_read == -1) {
3082 /* Returning ENOSYS means no data at all was sent.
3083 * Do this as a normal read. */
3084 if (errno == ENOSYS) {
3085 goto normal_readbraw;
3089 * Special hack for broken Linux with no working sendfile. If we
3090 * return EINTR we sent the header but not the rest of the data.
3091 * Fake this up by doing read/write calls.
3093 if (errno == EINTR) {
3094 /* Ensure we don't do this again. */
3095 set_use_sendfile(SNUM(conn), False);
3096 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3098 if (fake_sendfile(fsp, startpos, nread) == -1) {
3099 DEBUG(0,("send_file_readbraw: "
3100 "fake_sendfile failed for "
3104 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3109 DEBUG(0,("send_file_readbraw: sendfile failed for "
3110 "file %s (%s). Terminating\n",
3111 fsp_str_dbg(fsp), strerror(errno)));
3112 exit_server_cleanly("send_file_readbraw sendfile failed");
3113 } else if (sendfile_read == 0) {
3115 * Some sendfile implementations return 0 to indicate
3116 * that there was a short read, but nothing was
3117 * actually written to the socket. In this case,
3118 * fallback to the normal read path so the header gets
3119 * the correct byte count.
3121 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3122 "bytes falling back to the normal read: "
3123 "%s\n", fsp_str_dbg(fsp)));
3124 goto normal_readbraw;
3127 /* Deal with possible short send. */
3128 if (sendfile_read != 4+nread) {
3129 sendfile_short_send(fsp, sendfile_read, 4, nread);
3136 outbuf = talloc_array(NULL, char, nread+4);
3138 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3139 (unsigned)(nread+4)));
3140 reply_readbraw_error(sconn);
3145 ret = read_file(fsp,outbuf+4,startpos,nread);
3146 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3155 _smb_setlen(outbuf,ret);
3156 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3157 char addr[INET6_ADDRSTRLEN];
3159 * Try and give an error message saying what
3162 DEBUG(0, ("write_data failed for client %s. "
3164 get_peer_addr(fsp->conn->sconn->sock, addr,
3171 TALLOC_FREE(outbuf);
3174 /****************************************************************************
3175 Reply to a readbraw (core+ protocol).
3176 ****************************************************************************/
3178 void reply_readbraw(struct smb_request *req)
3180 connection_struct *conn = req->conn;
3181 struct smbd_server_connection *sconn = req->sconn;
3182 ssize_t maxcount,mincount;
3186 struct lock_struct lock;
3189 START_PROFILE(SMBreadbraw);
3191 if (srv_is_signing_active(sconn) ||
3192 is_encrypted_packet(sconn, req->inbuf)) {
3193 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3194 "raw reads/writes are disallowed.");
3198 reply_readbraw_error(sconn);
3199 END_PROFILE(SMBreadbraw);
3203 if (sconn->smb1.echo_handler.trusted_fde) {
3204 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3205 "'async smb echo handler = yes'\n"));
3206 reply_readbraw_error(sconn);
3207 END_PROFILE(SMBreadbraw);
3212 * Special check if an oplock break has been issued
3213 * and the readraw request croses on the wire, we must
3214 * return a zero length response here.
3217 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3220 * We have to do a check_fsp by hand here, as
3221 * we must always return 4 zero bytes on error,
3225 if (!fsp || !conn || conn != fsp->conn ||
3226 req->vuid != fsp->vuid ||
3227 fsp->is_directory || fsp->fh->fd == -1) {
3229 * fsp could be NULL here so use the value from the packet. JRA.
3231 DEBUG(3,("reply_readbraw: fnum %d not valid "
3233 (int)SVAL(req->vwv+0, 0)));
3234 reply_readbraw_error(sconn);
3235 END_PROFILE(SMBreadbraw);
3239 /* Do a "by hand" version of CHECK_READ. */
3240 if (!(fsp->can_read ||
3241 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3242 (fsp->access_mask & FILE_EXECUTE)))) {
3243 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3244 (int)SVAL(req->vwv+0, 0)));
3245 reply_readbraw_error(sconn);
3246 END_PROFILE(SMBreadbraw);
3250 flush_write_cache(fsp, READRAW_FLUSH);
3252 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3253 if(req->wct == 10) {
3255 * This is a large offset (64 bit) read.
3258 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3261 DEBUG(0,("reply_readbraw: negative 64 bit "
3262 "readraw offset (%.0f) !\n",
3263 (double)startpos ));
3264 reply_readbraw_error(sconn);
3265 END_PROFILE(SMBreadbraw);
3270 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3271 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3273 /* ensure we don't overrun the packet size */
3274 maxcount = MIN(65535,maxcount);
3276 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3277 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3280 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3281 reply_readbraw_error(sconn);
3282 END_PROFILE(SMBreadbraw);
3286 if (fsp_stat(fsp) == 0) {
3287 size = fsp->fsp_name->st.st_ex_size;
3290 if (startpos >= size) {
3293 nread = MIN(maxcount,(size - startpos));
3296 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3297 if (nread < mincount)
3301 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3302 "min=%lu nread=%lu\n",
3303 fsp_fnum_dbg(fsp), (double)startpos,
3304 (unsigned long)maxcount,
3305 (unsigned long)mincount,
3306 (unsigned long)nread ) );
3308 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3310 DEBUG(5,("reply_readbraw finished\n"));
3312 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3314 END_PROFILE(SMBreadbraw);
3319 #define DBGC_CLASS DBGC_LOCKING
3321 /****************************************************************************
3322 Reply to a lockread (core+ protocol).
3323 ****************************************************************************/
3325 void reply_lockread(struct smb_request *req)
3327 connection_struct *conn = req->conn;
3334 struct byte_range_lock *br_lck = NULL;
3336 struct smbd_server_connection *sconn = req->sconn;
3338 START_PROFILE(SMBlockread);
3341 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3342 END_PROFILE(SMBlockread);
3346 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3348 if (!check_fsp(conn, req, fsp)) {
3349 END_PROFILE(SMBlockread);
3353 if (!CHECK_READ(fsp,req)) {
3354 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3355 END_PROFILE(SMBlockread);
3359 numtoread = SVAL(req->vwv+1, 0);
3360 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3362 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3364 reply_outbuf(req, 5, numtoread + 3);
3366 data = smb_buf(req->outbuf) + 3;
3369 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3370 * protocol request that predates the read/write lock concept.
3371 * Thus instead of asking for a read lock here we need to ask
3372 * for a write lock. JRA.
3373 * Note that the requested lock size is unaffected by max_recv.
3376 br_lck = do_lock(req->sconn->msg_ctx,
3378 (uint64_t)req->smbpid,
3379 (uint64_t)numtoread,
3383 False, /* Non-blocking lock. */
3387 TALLOC_FREE(br_lck);
3389 if (NT_STATUS_V(status)) {
3390 reply_nterror(req, status);
3391 END_PROFILE(SMBlockread);
3396 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3399 if (numtoread > sconn->smb1.negprot.max_recv) {
3400 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3401 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3402 (unsigned int)numtoread,
3403 (unsigned int)sconn->smb1.negprot.max_recv));
3404 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3406 nread = read_file(fsp,data,startpos,numtoread);
3409 reply_nterror(req, map_nt_error_from_unix(errno));
3410 END_PROFILE(SMBlockread);
3414 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3416 SSVAL(req->outbuf,smb_vwv0,nread);
3417 SSVAL(req->outbuf,smb_vwv5,nread+3);
3418 p = smb_buf(req->outbuf);
3419 SCVAL(p,0,0); /* pad byte. */
3422 DEBUG(3,("lockread %s num=%d nread=%d\n",
3423 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3425 END_PROFILE(SMBlockread);
3430 #define DBGC_CLASS DBGC_ALL
3432 /****************************************************************************
3434 ****************************************************************************/
3436 void reply_read(struct smb_request *req)
3438 connection_struct *conn = req->conn;
3445 struct lock_struct lock;
3446 struct smbd_server_connection *sconn = req->sconn;
3448 START_PROFILE(SMBread);
3451 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3452 END_PROFILE(SMBread);
3456 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3458 if (!check_fsp(conn, req, fsp)) {
3459 END_PROFILE(SMBread);
3463 if (!CHECK_READ(fsp,req)) {
3464 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3465 END_PROFILE(SMBread);
3469 numtoread = SVAL(req->vwv+1, 0);
3470 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3472 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3475 * The requested read size cannot be greater than max_recv. JRA.
3477 if (numtoread > sconn->smb1.negprot.max_recv) {
3478 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3479 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3480 (unsigned int)numtoread,
3481 (unsigned int)sconn->smb1.negprot.max_recv));
3482 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3485 reply_outbuf(req, 5, numtoread+3);
3487 data = smb_buf(req->outbuf) + 3;
3489 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3490 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3493 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3494 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3495 END_PROFILE(SMBread);
3500 nread = read_file(fsp,data,startpos,numtoread);
3503 reply_nterror(req, map_nt_error_from_unix(errno));
3507 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3509 SSVAL(req->outbuf,smb_vwv0,nread);
3510 SSVAL(req->outbuf,smb_vwv5,nread+3);
3511 SCVAL(smb_buf(req->outbuf),0,1);
3512 SSVAL(smb_buf(req->outbuf),1,nread);
3514 DEBUG(3, ("read %s num=%d nread=%d\n",
3515 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3518 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3520 END_PROFILE(SMBread);
3524 /****************************************************************************
3526 ****************************************************************************/
3528 static int setup_readX_header(struct smb_request *req, char *outbuf,
3533 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3535 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3537 SCVAL(outbuf,smb_vwv0,0xFF);
3538 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3539 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3540 SSVAL(outbuf,smb_vwv6,
3541 (smb_wct - 4) /* offset from smb header to wct */
3542 + 1 /* the wct field */
3543 + 12 * sizeof(uint16_t) /* vwv */
3544 + 2); /* the buflen field */
3545 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3546 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3547 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3548 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3552 /****************************************************************************
3553 Reply to a read and X - possibly using sendfile.
3554 ****************************************************************************/
3556 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3557 files_struct *fsp, off_t startpos,
3561 struct lock_struct lock;
3562 int saved_errno = 0;
3564 if(fsp_stat(fsp) == -1) {
3565 reply_nterror(req, map_nt_error_from_unix(errno));
3569 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3570 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3573 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3574 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3578 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3579 (startpos > fsp->fsp_name->st.st_ex_size)
3580 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3582 * We already know that we would do a short read, so don't
3583 * try the sendfile() path.
3585 goto nosendfile_read;
3589 * We can only use sendfile on a non-chained packet
3590 * but we can use on a non-oplocked file. tridge proved this
3591 * on a train in Germany :-). JRA.
3594 if (!req_is_in_chain(req) &&
3595 !is_encrypted_packet(req->sconn, req->inbuf) &&
3596 (fsp->base_fsp == NULL) &&
3597 (fsp->wcp == NULL) &&
3598 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3599 uint8 headerbuf[smb_size + 12 * 2];
3603 * Set up the packet header before send. We
3604 * assume here the sendfile will work (get the
3605 * correct amount of data).
3608 header = data_blob_const(headerbuf, sizeof(headerbuf));
3610 construct_reply_common_req(req, (char *)headerbuf);
3611 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3613 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3614 startpos, smb_maxcnt);
3616 /* Returning ENOSYS means no data at all was sent.
3617 Do this as a normal read. */
3618 if (errno == ENOSYS) {
3623 * Special hack for broken Linux with no working sendfile. If we
3624 * return EINTR we sent the header but not the rest of the data.
3625 * Fake this up by doing read/write calls.
3628 if (errno == EINTR) {
3629 /* Ensure we don't do this again. */
3630 set_use_sendfile(SNUM(conn), False);
3631 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3632 nread = fake_sendfile(fsp, startpos,
3635 DEBUG(0,("send_file_readX: "
3636 "fake_sendfile failed for "
3640 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3642 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3643 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3644 /* No outbuf here means successful sendfile. */
3648 DEBUG(0,("send_file_readX: sendfile failed for file "
3649 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3651 exit_server_cleanly("send_file_readX sendfile failed");
3652 } else if (nread == 0) {
3654 * Some sendfile implementations return 0 to indicate
3655 * that there was a short read, but nothing was
3656 * actually written to the socket. In this case,
3657 * fallback to the normal read path so the header gets
3658 * the correct byte count.
3660 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3661 "falling back to the normal read: %s\n",
3666 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3667 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3669 /* Deal with possible short send. */
3670 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3671 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3673 /* No outbuf here means successful sendfile. */
3674 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3675 SMB_PERFCOUNT_END(&req->pcd);
3681 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3682 uint8 headerbuf[smb_size + 2*12];
3684 construct_reply_common_req(req, (char *)headerbuf);
3685 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3687 /* Send out the header. */
3688 if (write_data(req->sconn->sock, (char *)headerbuf,
3689 sizeof(headerbuf)) != sizeof(headerbuf)) {
3691 char addr[INET6_ADDRSTRLEN];
3693 * Try and give an error message saying what
3696 DEBUG(0, ("write_data failed for client %s. "
3698 get_peer_addr(req->sconn->sock, addr,
3702 DEBUG(0,("send_file_readX: write_data failed for file "
3703 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3705 exit_server_cleanly("send_file_readX sendfile failed");
3707 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3709 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3710 "file %s (%s).\n", fsp_str_dbg(fsp),
3712 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3719 reply_outbuf(req, 12, smb_maxcnt);
3720 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3721 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3723 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3724 saved_errno = errno;
3726 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3729 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3733 setup_readX_header(req, (char *)req->outbuf, nread);
3735 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3736 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3740 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3741 TALLOC_FREE(req->outbuf);
3745 /****************************************************************************
3746 Reply to a read and X.
3747 ****************************************************************************/
3749 void reply_read_and_X(struct smb_request *req)
3751 struct smbd_server_connection *sconn = req->sconn;
3752 connection_struct *conn = req->conn;
3756 bool big_readX = False;
3758 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3761 START_PROFILE(SMBreadX);
3763 if ((req->wct != 10) && (req->wct != 12)) {
3764 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3768 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3769 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3770 smb_maxcnt = SVAL(req->vwv+5, 0);
3772 /* If it's an IPC, pass off the pipe handler. */
3774 reply_pipe_read_and_X(req);
3775 END_PROFILE(SMBreadX);
3779 if (!check_fsp(conn, req, fsp)) {
3780 END_PROFILE(SMBreadX);
3784 if (!CHECK_READ(fsp,req)) {
3785 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3786 END_PROFILE(SMBreadX);
3790 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_LARGE_READ_CAP) ||
3791 (get_remote_arch() == RA_SAMBA)) {
3793 * This is Samba only behavior (up to Samba 3.6)!
3795 * Windows 2008 R2 ignores the upper_size,
3796 * so we do unless unix extentions are active
3797 * or "smbclient" is talking to us.
3799 size_t upper_size = SVAL(req->vwv+7, 0);
3800 smb_maxcnt |= (upper_size<<16);
3801 if (upper_size > 1) {
3802 /* Can't do this on a chained packet. */
3803 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3804 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3805 END_PROFILE(SMBreadX);
3808 /* We currently don't do this on signed or sealed data. */
3809 if (srv_is_signing_active(req->sconn) ||
3810 is_encrypted_packet(req->sconn, req->inbuf)) {
3811 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3812 END_PROFILE(SMBreadX);
3815 /* Is there room in the reply for this data ? */
3816 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3818 NT_STATUS_INVALID_PARAMETER);
3819 END_PROFILE(SMBreadX);
3826 if (req->wct == 12) {
3828 * This is a large offset (64 bit) read.
3830 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
3835 NTSTATUS status = schedule_aio_read_and_X(conn,
3840 if (NT_STATUS_IS_OK(status)) {
3841 /* Read scheduled - we're done. */
3844 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3845 /* Real error - report to client. */
3846 END_PROFILE(SMBreadX);
3847 reply_nterror(req, status);
3850 /* NT_STATUS_RETRY - fall back to sync read. */
3853 smbd_lock_socket(req->sconn);
3854 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3855 smbd_unlock_socket(req->sconn);
3858 END_PROFILE(SMBreadX);
3862 /****************************************************************************
3863 Error replies to writebraw must have smb_wct == 1. Fix this up.
3864 ****************************************************************************/
3866 void error_to_writebrawerr(struct smb_request *req)
3868 uint8 *old_outbuf = req->outbuf;
3870 reply_outbuf(req, 1, 0);
3872 memcpy(req->outbuf, old_outbuf, smb_size);
3873 TALLOC_FREE(old_outbuf);
3876 /****************************************************************************
3877 Read 4 bytes of a smb packet and return the smb length of the packet.
3878 Store the result in the buffer. This version of the function will
3879 never return a session keepalive (length of zero).
3880 Timeout is in milliseconds.
3881 ****************************************************************************/
3883 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3886 uint8_t msgtype = NBSSkeepalive;
3888 while (msgtype == NBSSkeepalive) {
3891 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3893 if (!NT_STATUS_IS_OK(status)) {
3894 char addr[INET6_ADDRSTRLEN];
3895 /* Try and give an error message
3896 * saying what client failed. */
3897 DEBUG(0, ("read_fd_with_timeout failed for "
3898 "client %s read error = %s.\n",
3899 get_peer_addr(fd,addr,sizeof(addr)),
3900 nt_errstr(status)));
3904 msgtype = CVAL(inbuf, 0);
3907 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3908 (unsigned long)len));
3910 return NT_STATUS_OK;
3913 /****************************************************************************
3914 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3915 ****************************************************************************/
3917 void reply_writebraw(struct smb_request *req)
3919 connection_struct *conn = req->conn;
3922 ssize_t total_written=0;
3923 size_t numtowrite=0;
3926 const char *data=NULL;
3929 struct lock_struct lock;
3932 START_PROFILE(SMBwritebraw);
3935 * If we ever reply with an error, it must have the SMB command
3936 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3939 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3941 if (srv_is_signing_active(req->sconn)) {
3942 END_PROFILE(SMBwritebraw);
3943 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3944 "raw reads/writes are disallowed.");
3947 if (req->wct < 12) {
3948 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3949 error_to_writebrawerr(req);
3950 END_PROFILE(SMBwritebraw);
3954 if (req->sconn->smb1.echo_handler.trusted_fde) {
3955 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3956 "'async smb echo handler = yes'\n"));
3957 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3958 error_to_writebrawerr(req);
3959 END_PROFILE(SMBwritebraw);
3963 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3964 if (!check_fsp(conn, req, fsp)) {
3965 error_to_writebrawerr(req);
3966 END_PROFILE(SMBwritebraw);
3970 if (!CHECK_WRITE(fsp)) {
3971 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3972 error_to_writebrawerr(req);
3973 END_PROFILE(SMBwritebraw);
3977 tcount = IVAL(req->vwv+1, 0);
3978 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3979 write_through = BITSETW(req->vwv+7,0);
3981 /* We have to deal with slightly different formats depending
3982 on whether we are using the core+ or lanman1.0 protocol */
3984 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3985 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3986 data = smb_buf_const(req->inbuf);
3988 numtowrite = SVAL(req->vwv+10, 0);
3989 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3992 /* Ensure we don't write bytes past the end of this packet. */
3993 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3994 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3995 error_to_writebrawerr(req);
3996 END_PROFILE(SMBwritebraw);
4000 if (!fsp->print_file) {
4001 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4002 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4005 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4006 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4007 error_to_writebrawerr(req);
4008 END_PROFILE(SMBwritebraw);
4014 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4017 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4018 "wrote=%d sync=%d\n",
4019 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4020 (int)nwritten, (int)write_through));
4022 if (nwritten < (ssize_t)numtowrite) {
4023 reply_nterror(req, NT_STATUS_DISK_FULL);
4024 error_to_writebrawerr(req);
4028 total_written = nwritten;
4030 /* Allocate a buffer of 64k + length. */
4031 buf = talloc_array(NULL, char, 65540);
4033 reply_nterror(req, NT_STATUS_NO_MEMORY);
4034 error_to_writebrawerr(req);
4038 /* Return a SMBwritebraw message to the redirector to tell
4039 * it to send more bytes */
4041 memcpy(buf, req->inbuf, smb_size);
4042 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4043 SCVAL(buf,smb_com,SMBwritebraw);
4044 SSVALS(buf,smb_vwv0,0xFFFF);
4046 if (!srv_send_smb(req->sconn,
4048 false, 0, /* no signing */
4049 IS_CONN_ENCRYPTED(conn),
4051 exit_server_cleanly("reply_writebraw: srv_send_smb "
4055 /* Now read the raw data into the buffer and write it */
4056 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4058 if (!NT_STATUS_IS_OK(status)) {
4059 exit_server_cleanly("secondary writebraw failed");
4062 /* Set up outbuf to return the correct size */
4063 reply_outbuf(req, 1, 0);
4065 if (numtowrite != 0) {
4067 if (numtowrite > 0xFFFF) {
4068 DEBUG(0,("reply_writebraw: Oversize secondary write "
4069 "raw requested (%u). Terminating\n",
4070 (unsigned int)numtowrite ));
4071 exit_server_cleanly("secondary writebraw failed");
4074 if (tcount > nwritten+numtowrite) {
4075 DEBUG(3,("reply_writebraw: Client overestimated the "
4077 (int)tcount,(int)nwritten,(int)numtowrite));
4080 status = read_data(req->sconn->sock, buf+4, numtowrite);
4082 if (!NT_STATUS_IS_OK(status)) {
4083 char addr[INET6_ADDRSTRLEN];
4084 /* Try and give an error message
4085 * saying what client failed. */
4086 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4087 "raw read failed (%s) for client %s. "
4088 "Terminating\n", nt_errstr(status),
4089 get_peer_addr(req->sconn->sock, addr,
4091 exit_server_cleanly("secondary writebraw failed");
4094 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4095 if (nwritten == -1) {
4097 reply_nterror(req, map_nt_error_from_unix(errno));
4098 error_to_writebrawerr(req);
4102 if (nwritten < (ssize_t)numtowrite) {
4103 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4104 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4108 total_written += nwritten;
4113 SSVAL(req->outbuf,smb_vwv0,total_written);
4115 status = sync_file(conn, fsp, write_through);
4116 if (!NT_STATUS_IS_OK(status)) {
4117 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4118 fsp_str_dbg(fsp), nt_errstr(status)));
4119 reply_nterror(req, status);
4120 error_to_writebrawerr(req);
4124 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4126 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4127 (int)total_written));
4129 if (!fsp->print_file) {
4130 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4133 /* We won't return a status if write through is not selected - this
4134 * follows what WfWg does */
4135 END_PROFILE(SMBwritebraw);
4137 if (!write_through && total_written==tcount) {
4139 #if RABBIT_PELLET_FIX
4141 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4142 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4145 if (!send_keepalive(req->sconn->sock)) {
4146 exit_server_cleanly("reply_writebraw: send of "
4147 "keepalive failed");
4150 TALLOC_FREE(req->outbuf);
4155 if (!fsp->print_file) {
4156 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4159 END_PROFILE(SMBwritebraw);
4164 #define DBGC_CLASS DBGC_LOCKING
4166 /****************************************************************************
4167 Reply to a writeunlock (core+).
4168 ****************************************************************************/
4170 void reply_writeunlock(struct smb_request *req)
4172 connection_struct *conn = req->conn;
4173 ssize_t nwritten = -1;
4177 NTSTATUS status = NT_STATUS_OK;
4179 struct lock_struct lock;
4180 int saved_errno = 0;
4182 START_PROFILE(SMBwriteunlock);
4185 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4186 END_PROFILE(SMBwriteunlock);
4190 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4192 if (!check_fsp(conn, req, fsp)) {
4193 END_PROFILE(SMBwriteunlock);
4197 if (!CHECK_WRITE(fsp)) {
4198 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4199 END_PROFILE(SMBwriteunlock);
4203 numtowrite = SVAL(req->vwv+1, 0);
4204 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4205 data = (const char *)req->buf + 3;
4207 if (!fsp->print_file && numtowrite > 0) {
4208 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4209 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4212 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4213 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4214 END_PROFILE(SMBwriteunlock);
4219 /* The special X/Open SMB protocol handling of
4220 zero length writes is *NOT* done for
4222 if(numtowrite == 0) {
4225 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4226 saved_errno = errno;
4229 status = sync_file(conn, fsp, False /* write through */);
4230 if (!NT_STATUS_IS_OK(status)) {
4231 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4232 fsp_str_dbg(fsp), nt_errstr(status)));
4233 reply_nterror(req, status);
4238 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4242 if((nwritten < numtowrite) && (numtowrite != 0)) {
4243 reply_nterror(req, NT_STATUS_DISK_FULL);
4247 if (numtowrite && !fsp->print_file) {
4248 status = do_unlock(req->sconn->msg_ctx,
4250 (uint64_t)req->smbpid,
4251 (uint64_t)numtowrite,
4255 if (NT_STATUS_V(status)) {
4256 reply_nterror(req, status);
4261 reply_outbuf(req, 1, 0);
4263 SSVAL(req->outbuf,smb_vwv0,nwritten);
4265 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4266 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4269 if (numtowrite && !fsp->print_file) {
4270 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4273 END_PROFILE(SMBwriteunlock);
4278 #define DBGC_CLASS DBGC_ALL
4280 /****************************************************************************
4282 ****************************************************************************/
4284 void reply_write(struct smb_request *req)
4286 connection_struct *conn = req->conn;
4288 ssize_t nwritten = -1;
4292 struct lock_struct lock;
4294 int saved_errno = 0;
4296 START_PROFILE(SMBwrite);
4299 END_PROFILE(SMBwrite);
4300 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4304 /* If it's an IPC, pass off the pipe handler. */
4306 reply_pipe_write(req);
4307 END_PROFILE(SMBwrite);
4311 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4313 if (!check_fsp(conn, req, fsp)) {
4314 END_PROFILE(SMBwrite);
4318 if (!CHECK_WRITE(fsp)) {
4319 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4320 END_PROFILE(SMBwrite);
4324 numtowrite = SVAL(req->vwv+1, 0);
4325 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4326 data = (const char *)req->buf + 3;
4328 if (!fsp->print_file) {
4329 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4330 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4333 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4334 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4335 END_PROFILE(SMBwrite);
4341 * X/Open SMB protocol says that if smb_vwv1 is
4342 * zero then the file size should be extended or
4343 * truncated to the size given in smb_vwv[2-3].
4346 if(numtowrite == 0) {
4348 * This is actually an allocate call, and set EOF. JRA.
4350 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4352 reply_nterror(req, NT_STATUS_DISK_FULL);
4355 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4357 reply_nterror(req, NT_STATUS_DISK_FULL);
4360 trigger_write_time_update_immediate(fsp);
4362 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4365 status = sync_file(conn, fsp, False);
4366 if (!NT_STATUS_IS_OK(status)) {
4367 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4368 fsp_str_dbg(fsp), nt_errstr(status)));
4369 reply_nterror(req, status);
4374 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4378 if((nwritten == 0) && (numtowrite != 0)) {
4379 reply_nterror(req, NT_STATUS_DISK_FULL);
4383 reply_outbuf(req, 1, 0);
4385 SSVAL(req->outbuf,smb_vwv0,nwritten);
4387 if (nwritten < (ssize_t)numtowrite) {
4388 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4389 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4392 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4395 if (!fsp->print_file) {
4396 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4399 END_PROFILE(SMBwrite);
4403 /****************************************************************************
4404 Ensure a buffer is a valid writeX for recvfile purposes.
4405 ****************************************************************************/
4407 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4408 (2*14) + /* word count (including bcc) */ \
4411 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4412 const uint8_t *inbuf)
4415 connection_struct *conn = NULL;
4416 unsigned int doff = 0;
4417 size_t len = smb_len_large(inbuf);
4418 struct smbXsrv_tcon *tcon;
4422 if (is_encrypted_packet(sconn, inbuf)) {
4423 /* Can't do this on encrypted
4428 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4432 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4433 CVAL(inbuf,smb_wct) != 14) {
4434 DEBUG(10,("is_valid_writeX_buffer: chained or "
4435 "invalid word length.\n"));
4439 status = smb1srv_tcon_lookup(sconn->conn, SVAL(inbuf, smb_tid),
4441 if (!NT_STATUS_IS_OK(status)) {
4442 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4445 conn = tcon->compat;
4448 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4451 if (IS_PRINT(conn)) {
4452 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4455 doff = SVAL(inbuf,smb_vwv11);
4457 numtowrite = SVAL(inbuf,smb_vwv10);
4459 if (len > doff && len - doff > 0xFFFF) {
4460 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4463 if (numtowrite == 0) {
4464 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4468 /* Ensure the sizes match up. */
4469 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4470 /* no pad byte...old smbclient :-( */
4471 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4473 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4477 if (len - doff != numtowrite) {
4478 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4479 "len = %u, doff = %u, numtowrite = %u\n",
4482 (unsigned int)numtowrite ));
4486 DEBUG(10,("is_valid_writeX_buffer: true "
4487 "len = %u, doff = %u, numtowrite = %u\n",
4490 (unsigned int)numtowrite ));
4495 /****************************************************************************
4496 Reply to a write and X.
4497 ****************************************************************************/
4499 void reply_write_and_X(struct smb_request *req)
4501 connection_struct *conn = req->conn;
4503 struct lock_struct lock;
4508 unsigned int smb_doff;
4509 unsigned int smblen;
4512 int saved_errno = 0;
4514 START_PROFILE(SMBwriteX);
4516 if ((req->wct != 12) && (req->wct != 14)) {
4517 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4521 numtowrite = SVAL(req->vwv+10, 0);
4522 smb_doff = SVAL(req->vwv+11, 0);
4523 smblen = smb_len(req->inbuf);
4525 if (req->unread_bytes > 0xFFFF ||
4526 (smblen > smb_doff &&
4527 smblen - smb_doff > 0xFFFF)) {
4528 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4531 if (req->unread_bytes) {
4532 /* Can't do a recvfile write on IPC$ */
4534 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4537 if (numtowrite != req->unread_bytes) {
4538 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4542 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4543 smb_doff + numtowrite > smblen) {
4544 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4549 /* If it's an IPC, pass off the pipe handler. */
4551 if (req->unread_bytes) {
4552 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4555 reply_pipe_write_and_X(req);
4559 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4560 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4561 write_through = BITSETW(req->vwv+7,0);
4563 if (!check_fsp(conn, req, fsp)) {
4567 if (!CHECK_WRITE(fsp)) {
4568 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4572 data = smb_base(req->inbuf) + smb_doff;
4574 if(req->wct == 14) {
4576 * This is a large offset (64 bit) write.
4578 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4582 /* X/Open SMB protocol says that, unlike SMBwrite
4583 if the length is zero then NO truncation is
4584 done, just a write of zero. To truncate a file,
4587 if(numtowrite == 0) {
4590 if (req->unread_bytes == 0) {
4591 status = schedule_aio_write_and_X(conn,
4598 if (NT_STATUS_IS_OK(status)) {
4599 /* write scheduled - we're done. */
4602 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4603 /* Real error - report to client. */
4604 reply_nterror(req, status);
4607 /* NT_STATUS_RETRY - fall through to sync write. */
4610 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4611 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4614 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4615 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4619 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4620 saved_errno = errno;
4622 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4626 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4630 if((nwritten == 0) && (numtowrite != 0)) {
4631 reply_nterror(req, NT_STATUS_DISK_FULL);
4635 reply_outbuf(req, 6, 0);
4636 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4637 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4638 SSVAL(req->outbuf,smb_vwv2,nwritten);
4639 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4641 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4642 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4644 status = sync_file(conn, fsp, write_through);
4645 if (!NT_STATUS_IS_OK(status)) {
4646 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4647 fsp_str_dbg(fsp), nt_errstr(status)));
4648 reply_nterror(req, status);
4652 END_PROFILE(SMBwriteX);
4656 if (req->unread_bytes) {
4657 /* writeX failed. drain socket. */
4658 if (drain_socket(req->sconn->sock, req->unread_bytes) !=
4659 req->unread_bytes) {
4660 smb_panic("failed to drain pending bytes");
4662 req->unread_bytes = 0;
4665 END_PROFILE(SMBwriteX);
4669 /****************************************************************************
4671 ****************************************************************************/
4673 void reply_lseek(struct smb_request *req)
4675 connection_struct *conn = req->conn;
4681 START_PROFILE(SMBlseek);
4684 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4685 END_PROFILE(SMBlseek);
4689 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4691 if (!check_fsp(conn, req, fsp)) {
4695 flush_write_cache(fsp, SEEK_FLUSH);
4697 mode = SVAL(req->vwv+1, 0) & 3;
4698 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4699 startpos = (off_t)IVALS(req->vwv+2, 0);
4708 res = fsp->fh->pos + startpos;
4719 if (umode == SEEK_END) {
4720 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4721 if(errno == EINVAL) {
4722 off_t current_pos = startpos;
4724 if(fsp_stat(fsp) == -1) {
4726 map_nt_error_from_unix(errno));
4727 END_PROFILE(SMBlseek);
4731 current_pos += fsp->fsp_name->st.st_ex_size;
4733 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4738 reply_nterror(req, map_nt_error_from_unix(errno));
4739 END_PROFILE(SMBlseek);
4746 reply_outbuf(req, 2, 0);
4747 SIVAL(req->outbuf,smb_vwv0,res);
4749 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4750 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
4752 END_PROFILE(SMBlseek);
4756 /****************************************************************************
4758 ****************************************************************************/
4760 void reply_flush(struct smb_request *req)
4762 connection_struct *conn = req->conn;
4766 START_PROFILE(SMBflush);
4769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4773 fnum = SVAL(req->vwv+0, 0);
4774 fsp = file_fsp(req, fnum);
4776 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4781 file_sync_all(conn);
4783 NTSTATUS status = sync_file(conn, fsp, True);
4784 if (!NT_STATUS_IS_OK(status)) {
4785 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4786 fsp_str_dbg(fsp), nt_errstr(status)));
4787 reply_nterror(req, status);
4788 END_PROFILE(SMBflush);
4793 reply_outbuf(req, 0, 0);
4795 DEBUG(3,("flush\n"));
4796 END_PROFILE(SMBflush);
4800 /****************************************************************************
4802 conn POINTER CAN BE NULL HERE !
4803 ****************************************************************************/
4805 void reply_exit(struct smb_request *req)
4807 START_PROFILE(SMBexit);
4809 file_close_pid(req->sconn, req->smbpid, req->vuid);
4811 reply_outbuf(req, 0, 0);
4813 DEBUG(3,("exit\n"));
4815 END_PROFILE(SMBexit);
4819 struct reply_close_state {
4821 struct smb_request *smbreq;
4824 static void do_smb1_close(struct tevent_req *req);
4826 void reply_close(struct smb_request *req)
4828 connection_struct *conn = req->conn;
4829 NTSTATUS status = NT_STATUS_OK;
4830 files_struct *fsp = NULL;
4831 START_PROFILE(SMBclose);
4834 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4835 END_PROFILE(SMBclose);
4839 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4842 * We can only use check_fsp if we know it's not a directory.
4845 if (!check_fsp_open(conn, req, fsp)) {
4846 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4847 END_PROFILE(SMBclose);
4851 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
4852 fsp->is_directory ? "directory" : "file",
4853 fsp->fh->fd, fsp_fnum_dbg(fsp),
4854 conn->num_files_open));
4856 if (!fsp->is_directory) {
4860 * Take care of any time sent in the close.
4863 t = srv_make_unix_date3(req->vwv+1);
4864 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4867 if (fsp->num_aio_requests != 0) {
4869 struct reply_close_state *state;
4871 DEBUG(10, ("closing with aio %u requests pending\n",
4872 fsp->num_aio_requests));
4875 * We depend on the aio_extra destructor to take care of this
4876 * close request once fsp->num_aio_request drops to 0.
4879 fsp->deferred_close = tevent_wait_send(
4880 fsp, fsp->conn->sconn->ev_ctx);
4881 if (fsp->deferred_close == NULL) {
4882 status = NT_STATUS_NO_MEMORY;
4886 state = talloc(fsp, struct reply_close_state);
4887 if (state == NULL) {
4888 TALLOC_FREE(fsp->deferred_close);
4889 status = NT_STATUS_NO_MEMORY;
4893 state->smbreq = talloc_move(fsp, &req);
4894 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
4896 END_PROFILE(SMBclose);
4901 * close_file() returns the unix errno if an error was detected on
4902 * close - normally this is due to a disk full error. If not then it
4903 * was probably an I/O error.
4906 status = close_file(req, fsp, NORMAL_CLOSE);
4908 if (!NT_STATUS_IS_OK(status)) {
4909 reply_nterror(req, status);
4910 END_PROFILE(SMBclose);
4914 reply_outbuf(req, 0, 0);
4915 END_PROFILE(SMBclose);
4919 static void do_smb1_close(struct tevent_req *req)
4921 struct reply_close_state *state = tevent_req_callback_data(
4922 req, struct reply_close_state);
4923 struct smb_request *smbreq;
4927 ret = tevent_wait_recv(req);
4930 DEBUG(10, ("tevent_wait_recv returned %s\n",
4933 * Continue anyway, this should never happen
4938 * fsp->smb2_close_request right now is a talloc grandchild of
4939 * fsp. When we close_file(fsp), it would go with it. No chance to
4942 smbreq = talloc_move(talloc_tos(), &state->smbreq);
4944 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
4945 if (NT_STATUS_IS_OK(status)) {
4946 reply_outbuf(smbreq, 0, 0);
4948 reply_nterror(smbreq, status);
4950 if (!srv_send_smb(smbreq->sconn,
4951 (char *)smbreq->outbuf,
4954 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
4956 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
4959 TALLOC_FREE(smbreq);
4962 /****************************************************************************
4963 Reply to a writeclose (Core+ protocol).
4964 ****************************************************************************/
4966 void reply_writeclose(struct smb_request *req)
4968 connection_struct *conn = req->conn;
4970 ssize_t nwritten = -1;
4971 NTSTATUS close_status = NT_STATUS_OK;
4974 struct timespec mtime;
4976 struct lock_struct lock;
4978 START_PROFILE(SMBwriteclose);
4981 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4982 END_PROFILE(SMBwriteclose);
4986 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4988 if (!check_fsp(conn, req, fsp)) {
4989 END_PROFILE(SMBwriteclose);
4992 if (!CHECK_WRITE(fsp)) {
4993 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4994 END_PROFILE(SMBwriteclose);
4998 numtowrite = SVAL(req->vwv+1, 0);
4999 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5000 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5001 data = (const char *)req->buf + 1;
5003 if (!fsp->print_file) {
5004 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5005 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5008 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5009 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5010 END_PROFILE(SMBwriteclose);
5015 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5017 set_close_write_time(fsp, mtime);
5020 * More insanity. W2K only closes the file if writelen > 0.
5025 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5026 "file %s\n", fsp_str_dbg(fsp)));
5027 close_status = close_file(req, fsp, NORMAL_CLOSE);
5030 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5031 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5032 conn->num_files_open));
5034 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5035 reply_nterror(req, NT_STATUS_DISK_FULL);
5039 if(!NT_STATUS_IS_OK(close_status)) {
5040 reply_nterror(req, close_status);
5044 reply_outbuf(req, 1, 0);
5046 SSVAL(req->outbuf,smb_vwv0,nwritten);
5049 if (numtowrite && !fsp->print_file) {
5050 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5053 END_PROFILE(SMBwriteclose);
5058 #define DBGC_CLASS DBGC_LOCKING
5060 /****************************************************************************
5062 ****************************************************************************/
5064 void reply_lock(struct smb_request *req)
5066 connection_struct *conn = req->conn;
5067 uint64_t count,offset;
5070 struct byte_range_lock *br_lck = NULL;
5072 START_PROFILE(SMBlock);
5075 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5076 END_PROFILE(SMBlock);
5080 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5082 if (!check_fsp(conn, req, fsp)) {
5083 END_PROFILE(SMBlock);
5087 count = (uint64_t)IVAL(req->vwv+1, 0);
5088 offset = (uint64_t)IVAL(req->vwv+3, 0);
5090 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5091 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5093 br_lck = do_lock(req->sconn->msg_ctx,
5095 (uint64_t)req->smbpid,
5100 False, /* Non-blocking lock. */
5105 TALLOC_FREE(br_lck);
5107 if (NT_STATUS_V(status)) {
5108 reply_nterror(req, status);
5109 END_PROFILE(SMBlock);
5113 reply_outbuf(req, 0, 0);
5115 END_PROFILE(SMBlock);
5119 /****************************************************************************
5121 ****************************************************************************/
5123 void reply_unlock(struct smb_request *req)
5125 connection_struct *conn = req->conn;
5126 uint64_t count,offset;
5130 START_PROFILE(SMBunlock);
5133 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5134 END_PROFILE(SMBunlock);
5138 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5140 if (!check_fsp(conn, req, fsp)) {
5141 END_PROFILE(SMBunlock);
5145 count = (uint64_t)IVAL(req->vwv+1, 0);
5146 offset = (uint64_t)IVAL(req->vwv+3, 0);
5148 status = do_unlock(req->sconn->msg_ctx,
5150 (uint64_t)req->smbpid,
5155 if (NT_STATUS_V(status)) {
5156 reply_nterror(req, status);
5157 END_PROFILE(SMBunlock);
5161 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5162 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5164 reply_outbuf(req, 0, 0);
5166 END_PROFILE(SMBunlock);
5171 #define DBGC_CLASS DBGC_ALL
5173 /****************************************************************************
5175 conn POINTER CAN BE NULL HERE !
5176 ****************************************************************************/
5178 void reply_tdis(struct smb_request *req)
5181 connection_struct *conn = req->conn;
5182 struct smbXsrv_tcon *tcon;
5184 START_PROFILE(SMBtdis);
5187 DEBUG(4,("Invalid connection in tdis\n"));
5188 reply_force_doserror(req, ERRSRV, ERRinvnid);
5189 END_PROFILE(SMBtdis);
5197 * TODO: cancel all outstanding requests on the tcon
5199 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5200 if (!NT_STATUS_IS_OK(status)) {
5201 DEBUG(0, ("reply_tdis: "
5202 "smbXsrv_tcon_disconnect() failed: %s\n",
5203 nt_errstr(status)));
5205 * If we hit this case, there is something completely
5206 * wrong, so we better disconnect the transport connection.
5208 END_PROFILE(SMBtdis);
5209 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5215 reply_outbuf(req, 0, 0);
5216 END_PROFILE(SMBtdis);
5220 /****************************************************************************
5222 conn POINTER CAN BE NULL HERE !
5223 ****************************************************************************/
5225 void reply_echo(struct smb_request *req)
5227 connection_struct *conn = req->conn;
5228 struct smb_perfcount_data local_pcd;
5229 struct smb_perfcount_data *cur_pcd;
5233 START_PROFILE(SMBecho);
5235 smb_init_perfcount_data(&local_pcd);
5238 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5239 END_PROFILE(SMBecho);
5243 smb_reverb = SVAL(req->vwv+0, 0);
5245 reply_outbuf(req, 1, req->buflen);
5247 /* copy any incoming data back out */
5248 if (req->buflen > 0) {
5249 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5252 if (smb_reverb > 100) {
5253 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5257 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5259 /* this makes sure we catch the request pcd */
5260 if (seq_num == smb_reverb) {
5261 cur_pcd = &req->pcd;
5263 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5264 cur_pcd = &local_pcd;
5267 SSVAL(req->outbuf,smb_vwv0,seq_num);
5269 show_msg((char *)req->outbuf);
5270 if (!srv_send_smb(req->sconn,
5271 (char *)req->outbuf,
5272 true, req->seqnum+1,
5273 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5275 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5278 DEBUG(3,("echo %d times\n", smb_reverb));
5280 TALLOC_FREE(req->outbuf);
5282 END_PROFILE(SMBecho);
5286 /****************************************************************************
5287 Reply to a printopen.
5288 ****************************************************************************/
5290 void reply_printopen(struct smb_request *req)
5292 connection_struct *conn = req->conn;
5296 START_PROFILE(SMBsplopen);
5299 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5300 END_PROFILE(SMBsplopen);
5304 if (!CAN_PRINT(conn)) {
5305 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5306 END_PROFILE(SMBsplopen);
5310 status = file_new(req, conn, &fsp);
5311 if(!NT_STATUS_IS_OK(status)) {
5312 reply_nterror(req, status);
5313 END_PROFILE(SMBsplopen);
5317 /* Open for exclusive use, write only. */
5318 status = print_spool_open(fsp, NULL, req->vuid);
5320 if (!NT_STATUS_IS_OK(status)) {
5321 file_free(req, fsp);
5322 reply_nterror(req, status);
5323 END_PROFILE(SMBsplopen);
5327 reply_outbuf(req, 1, 0);
5328 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5330 DEBUG(3,("openprint fd=%d %s\n",
5331 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5333 END_PROFILE(SMBsplopen);
5337 /****************************************************************************
5338 Reply to a printclose.
5339 ****************************************************************************/
5341 void reply_printclose(struct smb_request *req)
5343 connection_struct *conn = req->conn;
5347 START_PROFILE(SMBsplclose);
5350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5351 END_PROFILE(SMBsplclose);
5355 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5357 if (!check_fsp(conn, req, fsp)) {
5358 END_PROFILE(SMBsplclose);
5362 if (!CAN_PRINT(conn)) {
5363 reply_force_doserror(req, ERRSRV, ERRerror);
5364 END_PROFILE(SMBsplclose);
5368 DEBUG(3,("printclose fd=%d %s\n",
5369 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5371 status = close_file(req, fsp, NORMAL_CLOSE);
5373 if(!NT_STATUS_IS_OK(status)) {
5374 reply_nterror(req, status);
5375 END_PROFILE(SMBsplclose);
5379 reply_outbuf(req, 0, 0);
5381 END_PROFILE(SMBsplclose);
5385 /****************************************************************************
5386 Reply to a printqueue.
5387 ****************************************************************************/
5389 void reply_printqueue(struct smb_request *req)
5391 connection_struct *conn = req->conn;
5395 START_PROFILE(SMBsplretq);
5398 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5399 END_PROFILE(SMBsplretq);
5403 max_count = SVAL(req->vwv+0, 0);
5404 start_index = SVAL(req->vwv+1, 0);
5406 /* we used to allow the client to get the cnum wrong, but that
5407 is really quite gross and only worked when there was only
5408 one printer - I think we should now only accept it if they
5409 get it right (tridge) */
5410 if (!CAN_PRINT(conn)) {
5411 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5412 END_PROFILE(SMBsplretq);
5416 reply_outbuf(req, 2, 3);
5417 SSVAL(req->outbuf,smb_vwv0,0);
5418 SSVAL(req->outbuf,smb_vwv1,0);
5419 SCVAL(smb_buf(req->outbuf),0,1);
5420 SSVAL(smb_buf(req->outbuf),1,0);
5422 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5423 start_index, max_count));
5426 TALLOC_CTX *mem_ctx = talloc_tos();
5429 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5430 struct rpc_pipe_client *cli = NULL;
5431 struct dcerpc_binding_handle *b = NULL;
5432 struct policy_handle handle;
5433 struct spoolss_DevmodeContainer devmode_ctr;
5434 union spoolss_JobInfo *info;
5436 uint32_t num_to_get;
5440 ZERO_STRUCT(handle);
5442 status = rpc_pipe_open_interface(conn,
5443 &ndr_table_spoolss.syntax_id,
5445 conn->sconn->remote_address,
5446 conn->sconn->msg_ctx,
5448 if (!NT_STATUS_IS_OK(status)) {
5449 DEBUG(0, ("reply_printqueue: "
5450 "could not connect to spoolss: %s\n",
5451 nt_errstr(status)));
5452 reply_nterror(req, status);
5455 b = cli->binding_handle;
5457 ZERO_STRUCT(devmode_ctr);
5459 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5462 SEC_FLAG_MAXIMUM_ALLOWED,
5465 if (!NT_STATUS_IS_OK(status)) {
5466 reply_nterror(req, status);
5469 if (!W_ERROR_IS_OK(werr)) {
5470 reply_nterror(req, werror_to_ntstatus(werr));
5474 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5482 if (!W_ERROR_IS_OK(werr)) {
5483 reply_nterror(req, werror_to_ntstatus(werr));
5487 if (max_count > 0) {
5488 first = start_index;
5490 first = start_index + max_count + 1;
5493 if (first >= count) {
5496 num_to_get = first + MIN(ABS(max_count), count - first);
5499 for (i = first; i < num_to_get; i++) {
5502 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5504 uint16_t qrapjobid = pjobid_to_rap(sharename,
5505 info[i].info2.job_id);
5507 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5513 srv_put_dos_date2(p, 0, qtime);
5514 SCVAL(p, 4, qstatus);
5515 SSVAL(p, 5, qrapjobid);
5516 SIVAL(p, 7, info[i].info2.size);
5518 srvstr_push(blob, req->flags2, p+12,
5519 info[i].info2.notify_name, 16, STR_ASCII);
5521 if (message_push_blob(
5524 blob, sizeof(blob))) == -1) {
5525 reply_nterror(req, NT_STATUS_NO_MEMORY);
5531 SSVAL(req->outbuf,smb_vwv0,count);
5532 SSVAL(req->outbuf,smb_vwv1,
5533 (max_count>0?first+count:first-1));
5534 SCVAL(smb_buf(req->outbuf),0,1);
5535 SSVAL(smb_buf(req->outbuf),1,28*count);
5539 DEBUG(3, ("%u entries returned in queue\n",
5543 if (b && is_valid_policy_hnd(&handle)) {
5544 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5549 END_PROFILE(SMBsplretq);
5553 /****************************************************************************
5554 Reply to a printwrite.
5555 ****************************************************************************/
5557 void reply_printwrite(struct smb_request *req)
5559 connection_struct *conn = req->conn;
5564 START_PROFILE(SMBsplwr);
5567 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5568 END_PROFILE(SMBsplwr);
5572 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5574 if (!check_fsp(conn, req, fsp)) {
5575 END_PROFILE(SMBsplwr);
5579 if (!fsp->print_file) {
5580 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5581 END_PROFILE(SMBsplwr);
5585 if (!CHECK_WRITE(fsp)) {
5586 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5587 END_PROFILE(SMBsplwr);
5591 numtowrite = SVAL(req->buf, 1);
5593 if (req->buflen < numtowrite + 3) {
5594 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5595 END_PROFILE(SMBsplwr);
5599 data = (const char *)req->buf + 3;
5601 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5602 reply_nterror(req, map_nt_error_from_unix(errno));
5603 END_PROFILE(SMBsplwr);
5607 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
5609 END_PROFILE(SMBsplwr);
5613 /****************************************************************************
5615 ****************************************************************************/
5617 void reply_mkdir(struct smb_request *req)
5619 connection_struct *conn = req->conn;
5620 struct smb_filename *smb_dname = NULL;
5621 char *directory = NULL;
5623 TALLOC_CTX *ctx = talloc_tos();
5625 START_PROFILE(SMBmkdir);
5627 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5628 STR_TERMINATE, &status);
5629 if (!NT_STATUS_IS_OK(status)) {
5630 reply_nterror(req, status);
5634 status = filename_convert(ctx, conn,
5635 req->flags2 & FLAGS2_DFS_PATHNAMES,
5640 if (!NT_STATUS_IS_OK(status)) {
5641 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5642 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5643 ERRSRV, ERRbadpath);
5646 reply_nterror(req, status);
5650 status = create_directory(conn, req, smb_dname);
5652 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5654 if (!NT_STATUS_IS_OK(status)) {
5656 if (!use_nt_status()
5657 && NT_STATUS_EQUAL(status,
5658 NT_STATUS_OBJECT_NAME_COLLISION)) {
5660 * Yes, in the DOS error code case we get a
5661 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5662 * samba4 torture test.
5664 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5667 reply_nterror(req, status);
5671 reply_outbuf(req, 0, 0);
5673 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5675 TALLOC_FREE(smb_dname);
5676 END_PROFILE(SMBmkdir);
5680 /****************************************************************************
5682 ****************************************************************************/
5684 void reply_rmdir(struct smb_request *req)
5686 connection_struct *conn = req->conn;
5687 struct smb_filename *smb_dname = NULL;
5688 char *directory = NULL;
5690 TALLOC_CTX *ctx = talloc_tos();
5691 files_struct *fsp = NULL;
5693 struct smbd_server_connection *sconn = req->sconn;
5695 START_PROFILE(SMBrmdir);
5697 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5698 STR_TERMINATE, &status);
5699 if (!NT_STATUS_IS_OK(status)) {
5700 reply_nterror(req, status);
5704 status = filename_convert(ctx, conn,
5705 req->flags2 & FLAGS2_DFS_PATHNAMES,
5710 if (!NT_STATUS_IS_OK(status)) {
5711 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5712 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5713 ERRSRV, ERRbadpath);
5716 reply_nterror(req, status);
5720 if (is_ntfs_stream_smb_fname(smb_dname)) {
5721 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5725 status = SMB_VFS_CREATE_FILE(
5728 0, /* root_dir_fid */
5729 smb_dname, /* fname */
5730 DELETE_ACCESS, /* access_mask */
5731 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5733 FILE_OPEN, /* create_disposition*/
5734 FILE_DIRECTORY_FILE, /* create_options */
5735 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5736 0, /* oplock_request */
5737 0, /* allocation_size */
5738 0, /* private_flags */
5744 if (!NT_STATUS_IS_OK(status)) {
5745 if (open_was_deferred(req->sconn, req->mid)) {
5746 /* We have re-scheduled this call. */
5749 reply_nterror(req, status);
5753 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5754 if (!NT_STATUS_IS_OK(status)) {
5755 close_file(req, fsp, ERROR_CLOSE);
5756 reply_nterror(req, status);
5760 if (!set_delete_on_close(fsp, true,
5761 conn->session_info->security_token,
5762 conn->session_info->unix_token)) {
5763 close_file(req, fsp, ERROR_CLOSE);
5764 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5768 status = close_file(req, fsp, NORMAL_CLOSE);
5769 if (!NT_STATUS_IS_OK(status)) {
5770 reply_nterror(req, status);
5772 reply_outbuf(req, 0, 0);
5775 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5777 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5779 TALLOC_FREE(smb_dname);
5780 END_PROFILE(SMBrmdir);
5784 /*******************************************************************
5785 Resolve wildcards in a filename rename.
5786 ********************************************************************/
5788 static bool resolve_wildcards(TALLOC_CTX *ctx,
5793 char *name2_copy = NULL;
5798 char *p,*p2, *pname1, *pname2;
5800 name2_copy = talloc_strdup(ctx, name2);
5805 pname1 = strrchr_m(name1,'/');
5806 pname2 = strrchr_m(name2_copy,'/');
5808 if (!pname1 || !pname2) {
5812 /* Truncate the copy of name2 at the last '/' */
5815 /* Now go past the '/' */
5819 root1 = talloc_strdup(ctx, pname1);
5820 root2 = talloc_strdup(ctx, pname2);
5822 if (!root1 || !root2) {
5826 p = strrchr_m(root1,'.');
5829 ext1 = talloc_strdup(ctx, p+1);
5831 ext1 = talloc_strdup(ctx, "");
5833 p = strrchr_m(root2,'.');
5836 ext2 = talloc_strdup(ctx, p+1);
5838 ext2 = talloc_strdup(ctx, "");
5841 if (!ext1 || !ext2) {
5849 /* Hmmm. Should this be mb-aware ? */
5852 } else if (*p2 == '*') {
5854 root2 = talloc_asprintf(ctx, "%s%s",
5873 /* Hmmm. Should this be mb-aware ? */
5876 } else if (*p2 == '*') {
5878 ext2 = talloc_asprintf(ctx, "%s%s",
5894 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5899 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5911 /****************************************************************************
5912 Ensure open files have their names updated. Updated to notify other smbd's
5914 ****************************************************************************/
5916 static void rename_open_files(connection_struct *conn,
5917 struct share_mode_lock *lck,
5918 uint32_t orig_name_hash,
5919 const struct smb_filename *smb_fname_dst)
5922 bool did_rename = False;
5924 uint32_t new_name_hash = 0;
5926 for(fsp = file_find_di_first(conn->sconn, lck->data->id); fsp;
5927 fsp = file_find_di_next(fsp)) {
5928 /* fsp_name is a relative path under the fsp. To change this for other
5929 sharepaths we need to manipulate relative paths. */
5930 /* TODO - create the absolute path and manipulate the newname
5931 relative to the sharepath. */
5932 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5935 if (fsp->name_hash != orig_name_hash) {
5938 DEBUG(10, ("rename_open_files: renaming file %s "
5939 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
5940 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5941 smb_fname_str_dbg(smb_fname_dst)));
5943 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5944 if (NT_STATUS_IS_OK(status)) {
5946 new_name_hash = fsp->name_hash;
5951 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5952 "for %s\n", file_id_string_tos(&lck->data->id),
5953 smb_fname_str_dbg(smb_fname_dst)));
5956 /* Send messages to all smbd's (not ourself) that the name has changed. */
5957 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5958 orig_name_hash, new_name_hash,
5963 /****************************************************************************
5964 We need to check if the source path is a parent directory of the destination
5965 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5966 refuse the rename with a sharing violation. Under UNIX the above call can
5967 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5968 probably need to check that the client is a Windows one before disallowing
5969 this as a UNIX client (one with UNIX extensions) can know the source is a
5970 symlink and make this decision intelligently. Found by an excellent bug
5971 report from <AndyLiebman@aol.com>.
5972 ****************************************************************************/
5974 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5975 const struct smb_filename *smb_fname_dst)
5977 const char *psrc = smb_fname_src->base_name;
5978 const char *pdst = smb_fname_dst->base_name;
5981 if (psrc[0] == '.' && psrc[1] == '/') {
5984 if (pdst[0] == '.' && pdst[1] == '/') {
5987 if ((slen = strlen(psrc)) > strlen(pdst)) {
5990 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5994 * Do the notify calls from a rename
5997 static void notify_rename(connection_struct *conn, bool is_dir,
5998 const struct smb_filename *smb_fname_src,
5999 const struct smb_filename *smb_fname_dst)
6001 char *parent_dir_src = NULL;
6002 char *parent_dir_dst = NULL;
6005 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6006 : FILE_NOTIFY_CHANGE_FILE_NAME;
6008 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6009 &parent_dir_src, NULL) ||
6010 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6011 &parent_dir_dst, NULL)) {
6015 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6016 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6017 smb_fname_src->base_name);
6018 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6019 smb_fname_dst->base_name);
6022 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6023 smb_fname_src->base_name);
6024 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6025 smb_fname_dst->base_name);
6028 /* this is a strange one. w2k3 gives an additional event for
6029 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6030 files, but not directories */
6032 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6033 FILE_NOTIFY_CHANGE_ATTRIBUTES
6034 |FILE_NOTIFY_CHANGE_CREATION,
6035 smb_fname_dst->base_name);
6038 TALLOC_FREE(parent_dir_src);
6039 TALLOC_FREE(parent_dir_dst);
6042 /****************************************************************************
6043 Returns an error if the parent directory for a filename is open in an
6045 ****************************************************************************/
6047 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6048 const struct smb_filename *smb_fname_dst_in)
6050 char *parent_dir = NULL;
6051 struct smb_filename smb_fname_parent;
6053 files_struct *fsp = NULL;
6056 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6057 &parent_dir, NULL)) {
6058 return NT_STATUS_NO_MEMORY;
6060 ZERO_STRUCT(smb_fname_parent);
6061 smb_fname_parent.base_name = parent_dir;
6063 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6065 return map_nt_error_from_unix(errno);
6069 * We're only checking on this smbd here, mostly good
6070 * enough.. and will pass tests.
6073 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6074 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6075 fsp = file_find_di_next(fsp)) {
6076 if (fsp->access_mask & DELETE_ACCESS) {
6077 return NT_STATUS_SHARING_VIOLATION;
6080 return NT_STATUS_OK;
6083 /****************************************************************************
6084 Rename an open file - given an fsp.
6085 ****************************************************************************/
6087 NTSTATUS rename_internals_fsp(connection_struct *conn,
6089 const struct smb_filename *smb_fname_dst_in,
6091 bool replace_if_exists)
6093 TALLOC_CTX *ctx = talloc_tos();
6094 struct smb_filename *smb_fname_dst = NULL;
6095 NTSTATUS status = NT_STATUS_OK;
6096 struct share_mode_lock *lck = NULL;
6097 bool dst_exists, old_is_stream, new_is_stream;
6099 status = check_name(conn, smb_fname_dst_in->base_name);
6100 if (!NT_STATUS_IS_OK(status)) {
6104 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6105 if (!NT_STATUS_IS_OK(status)) {
6109 /* Make a copy of the dst smb_fname structs */
6111 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
6112 if (!NT_STATUS_IS_OK(status)) {
6117 * Check for special case with case preserving and not
6118 * case sensitive. If the old last component differs from the original
6119 * last component only by case, then we should allow
6120 * the rename (user is trying to change the case of the
6123 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6124 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6125 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6127 char *fname_dst_lcomp_base_mod = NULL;
6128 struct smb_filename *smb_fname_orig_lcomp = NULL;
6131 * Get the last component of the destination name.
6133 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6135 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6137 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6139 if (!fname_dst_lcomp_base_mod) {
6140 status = NT_STATUS_NO_MEMORY;
6145 * Create an smb_filename struct using the original last
6146 * component of the destination.
6148 status = create_synthetic_smb_fname_split(ctx,
6149 smb_fname_dst->original_lcomp, NULL,
6150 &smb_fname_orig_lcomp);
6151 if (!NT_STATUS_IS_OK(status)) {
6152 TALLOC_FREE(fname_dst_lcomp_base_mod);
6156 /* If the base names only differ by case, use original. */
6157 if(!strcsequal(fname_dst_lcomp_base_mod,
6158 smb_fname_orig_lcomp->base_name)) {
6161 * Replace the modified last component with the
6165 *last_slash = '\0'; /* Truncate at the '/' */
6166 tmp = talloc_asprintf(smb_fname_dst,
6168 smb_fname_dst->base_name,
6169 smb_fname_orig_lcomp->base_name);
6171 tmp = talloc_asprintf(smb_fname_dst,
6173 smb_fname_orig_lcomp->base_name);
6176 status = NT_STATUS_NO_MEMORY;
6177 TALLOC_FREE(fname_dst_lcomp_base_mod);
6178 TALLOC_FREE(smb_fname_orig_lcomp);
6181 TALLOC_FREE(smb_fname_dst->base_name);
6182 smb_fname_dst->base_name = tmp;
6185 /* If the stream_names only differ by case, use original. */
6186 if(!strcsequal(smb_fname_dst->stream_name,
6187 smb_fname_orig_lcomp->stream_name)) {
6189 /* Use the original stream. */
6190 tmp = talloc_strdup(smb_fname_dst,
6191 smb_fname_orig_lcomp->stream_name);
6193 status = NT_STATUS_NO_MEMORY;
6194 TALLOC_FREE(fname_dst_lcomp_base_mod);
6195 TALLOC_FREE(smb_fname_orig_lcomp);
6198 TALLOC_FREE(smb_fname_dst->stream_name);
6199 smb_fname_dst->stream_name = tmp;
6201 TALLOC_FREE(fname_dst_lcomp_base_mod);
6202 TALLOC_FREE(smb_fname_orig_lcomp);
6206 * If the src and dest names are identical - including case,
6207 * don't do the rename, just return success.
6210 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6211 strcsequal(fsp->fsp_name->stream_name,
6212 smb_fname_dst->stream_name)) {
6213 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6214 "- returning success\n",
6215 smb_fname_str_dbg(smb_fname_dst)));
6216 status = NT_STATUS_OK;
6220 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6221 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6223 /* Return the correct error code if both names aren't streams. */
6224 if (!old_is_stream && new_is_stream) {
6225 status = NT_STATUS_OBJECT_NAME_INVALID;
6229 if (old_is_stream && !new_is_stream) {
6230 status = NT_STATUS_INVALID_PARAMETER;
6234 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6236 if(!replace_if_exists && dst_exists) {
6237 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6238 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6239 smb_fname_str_dbg(smb_fname_dst)));
6240 status = NT_STATUS_OBJECT_NAME_COLLISION;
6245 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6246 &smb_fname_dst->st);
6247 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6249 /* The file can be open when renaming a stream */
6250 if (dst_fsp && !new_is_stream) {
6251 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6252 status = NT_STATUS_ACCESS_DENIED;
6257 /* Ensure we have a valid stat struct for the source. */
6258 status = vfs_stat_fsp(fsp);
6259 if (!NT_STATUS_IS_OK(status)) {
6263 status = can_rename(conn, fsp, attrs);
6265 if (!NT_STATUS_IS_OK(status)) {
6266 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6267 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6268 smb_fname_str_dbg(smb_fname_dst)));
6269 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6270 status = NT_STATUS_ACCESS_DENIED;
6274 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6275 status = NT_STATUS_ACCESS_DENIED;
6278 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6281 * We have the file open ourselves, so not being able to get the
6282 * corresponding share mode lock is a fatal error.
6285 SMB_ASSERT(lck != NULL);
6287 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6288 uint32 create_options = fsp->fh->private_options;
6290 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6291 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6292 smb_fname_str_dbg(smb_fname_dst)));
6294 if (!lp_posix_pathnames() &&
6295 (lp_map_archive(SNUM(conn)) ||
6296 lp_store_dos_attributes(SNUM(conn)))) {
6297 /* We must set the archive bit on the newly
6299 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6300 uint32_t old_dosmode = dos_mode(conn,
6302 file_set_dosmode(conn,
6304 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6310 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6313 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6316 * A rename acts as a new file create w.r.t. allowing an initial delete
6317 * on close, probably because in Windows there is a new handle to the
6318 * new file. If initial delete on close was requested but not
6319 * originally set, we need to set it here. This is probably not 100% correct,
6320 * but will work for the CIFSFS client which in non-posix mode
6321 * depends on these semantics. JRA.
6324 if (create_options & FILE_DELETE_ON_CLOSE) {
6325 status = can_set_delete_on_close(fsp, 0);
6327 if (NT_STATUS_IS_OK(status)) {
6328 /* Note that here we set the *inital* delete on close flag,
6329 * not the regular one. The magic gets handled in close. */
6330 fsp->initial_delete_on_close = True;
6334 status = NT_STATUS_OK;
6340 if (errno == ENOTDIR || errno == EISDIR) {
6341 status = NT_STATUS_OBJECT_NAME_COLLISION;
6343 status = map_nt_error_from_unix(errno);
6346 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6347 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6348 smb_fname_str_dbg(smb_fname_dst)));
6351 TALLOC_FREE(smb_fname_dst);
6356 /****************************************************************************
6357 The guts of the rename command, split out so it may be called by the NT SMB
6359 ****************************************************************************/
6361 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6362 connection_struct *conn,
6363 struct smb_request *req,
6364 struct smb_filename *smb_fname_src,
6365 struct smb_filename *smb_fname_dst,
6367 bool replace_if_exists,
6370 uint32_t access_mask)
6372 char *fname_src_dir = NULL;
6373 char *fname_src_mask = NULL;
6375 NTSTATUS status = NT_STATUS_OK;
6376 struct smb_Dir *dir_hnd = NULL;
6377 const char *dname = NULL;
6378 char *talloced = NULL;
6380 int create_options = 0;
6381 bool posix_pathnames = lp_posix_pathnames();
6384 * Split the old name into directory and last component
6385 * strings. Note that unix_convert may have stripped off a
6386 * leading ./ from both name and newname if the rename is
6387 * at the root of the share. We need to make sure either both
6388 * name and newname contain a / character or neither of them do
6389 * as this is checked in resolve_wildcards().
6392 /* Split up the directory from the filename/mask. */
6393 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6394 &fname_src_dir, &fname_src_mask);
6395 if (!NT_STATUS_IS_OK(status)) {
6396 status = NT_STATUS_NO_MEMORY;
6401 * We should only check the mangled cache
6402 * here if unix_convert failed. This means
6403 * that the path in 'mask' doesn't exist
6404 * on the file system and so we need to look
6405 * for a possible mangle. This patch from
6406 * Tine Smukavec <valentin.smukavec@hermes.si>.
6409 if (!VALID_STAT(smb_fname_src->st) &&
6410 mangle_is_mangled(fname_src_mask, conn->params)) {
6411 char *new_mask = NULL;
6412 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6415 TALLOC_FREE(fname_src_mask);
6416 fname_src_mask = new_mask;
6420 if (!src_has_wild) {
6424 * Only one file needs to be renamed. Append the mask back
6425 * onto the directory.
6427 TALLOC_FREE(smb_fname_src->base_name);
6428 if (ISDOT(fname_src_dir)) {
6429 /* Ensure we use canonical names on open. */
6430 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6434 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6439 if (!smb_fname_src->base_name) {
6440 status = NT_STATUS_NO_MEMORY;
6444 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6445 "case_preserve = %d, short case preserve = %d, "
6446 "directory = %s, newname = %s, "
6447 "last_component_dest = %s\n",
6448 conn->case_sensitive, conn->case_preserve,
6449 conn->short_case_preserve,
6450 smb_fname_str_dbg(smb_fname_src),
6451 smb_fname_str_dbg(smb_fname_dst),
6452 smb_fname_dst->original_lcomp));
6454 /* The dest name still may have wildcards. */
6455 if (dest_has_wild) {
6456 char *fname_dst_mod = NULL;
6457 if (!resolve_wildcards(smb_fname_dst,
6458 smb_fname_src->base_name,
6459 smb_fname_dst->base_name,
6461 DEBUG(6, ("rename_internals: resolve_wildcards "
6463 smb_fname_src->base_name,
6464 smb_fname_dst->base_name));
6465 status = NT_STATUS_NO_MEMORY;
6468 TALLOC_FREE(smb_fname_dst->base_name);
6469 smb_fname_dst->base_name = fname_dst_mod;
6472 ZERO_STRUCT(smb_fname_src->st);
6473 if (posix_pathnames) {
6474 SMB_VFS_LSTAT(conn, smb_fname_src);
6476 SMB_VFS_STAT(conn, smb_fname_src);
6479 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6480 create_options |= FILE_DIRECTORY_FILE;
6483 status = SMB_VFS_CREATE_FILE(
6486 0, /* root_dir_fid */
6487 smb_fname_src, /* fname */
6488 access_mask, /* access_mask */
6489 (FILE_SHARE_READ | /* share_access */
6491 FILE_OPEN, /* create_disposition*/
6492 create_options, /* create_options */
6493 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6494 0, /* oplock_request */
6495 0, /* allocation_size */
6496 0, /* private_flags */
6502 if (!NT_STATUS_IS_OK(status)) {
6503 DEBUG(3, ("Could not open rename source %s: %s\n",
6504 smb_fname_str_dbg(smb_fname_src),
6505 nt_errstr(status)));
6509 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6510 attrs, replace_if_exists);
6512 close_file(req, fsp, NORMAL_CLOSE);
6514 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6515 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6516 smb_fname_str_dbg(smb_fname_dst)));
6522 * Wildcards - process each file that matches.
6524 if (strequal(fname_src_mask, "????????.???")) {
6525 TALLOC_FREE(fname_src_mask);
6526 fname_src_mask = talloc_strdup(ctx, "*");
6527 if (!fname_src_mask) {
6528 status = NT_STATUS_NO_MEMORY;
6533 status = check_name(conn, fname_src_dir);
6534 if (!NT_STATUS_IS_OK(status)) {
6538 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6540 if (dir_hnd == NULL) {
6541 status = map_nt_error_from_unix(errno);
6545 status = NT_STATUS_NO_SUCH_FILE;
6547 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6548 * - gentest fix. JRA
6551 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6553 files_struct *fsp = NULL;
6554 char *destname = NULL;
6555 bool sysdir_entry = False;
6557 /* Quick check for "." and ".." */
6558 if (ISDOT(dname) || ISDOTDOT(dname)) {
6559 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6560 sysdir_entry = True;
6562 TALLOC_FREE(talloced);
6567 if (!is_visible_file(conn, fname_src_dir, dname,
6568 &smb_fname_src->st, false)) {
6569 TALLOC_FREE(talloced);
6573 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6574 TALLOC_FREE(talloced);
6579 status = NT_STATUS_OBJECT_NAME_INVALID;
6583 TALLOC_FREE(smb_fname_src->base_name);
6584 if (ISDOT(fname_src_dir)) {
6585 /* Ensure we use canonical names on open. */
6586 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6590 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6595 if (!smb_fname_src->base_name) {
6596 status = NT_STATUS_NO_MEMORY;
6600 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6601 smb_fname_dst->base_name,
6603 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6604 smb_fname_src->base_name, destname));
6605 TALLOC_FREE(talloced);
6609 status = NT_STATUS_NO_MEMORY;
6613 TALLOC_FREE(smb_fname_dst->base_name);
6614 smb_fname_dst->base_name = destname;
6616 ZERO_STRUCT(smb_fname_src->st);
6617 if (posix_pathnames) {
6618 SMB_VFS_LSTAT(conn, smb_fname_src);
6620 SMB_VFS_STAT(conn, smb_fname_src);
6625 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6626 create_options |= FILE_DIRECTORY_FILE;
6629 status = SMB_VFS_CREATE_FILE(
6632 0, /* root_dir_fid */
6633 smb_fname_src, /* fname */
6634 access_mask, /* access_mask */
6635 (FILE_SHARE_READ | /* share_access */
6637 FILE_OPEN, /* create_disposition*/
6638 create_options, /* create_options */
6639 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6640 0, /* oplock_request */
6641 0, /* allocation_size */
6642 0, /* private_flags */
6648 if (!NT_STATUS_IS_OK(status)) {
6649 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6650 "returned %s rename %s -> %s\n",
6652 smb_fname_str_dbg(smb_fname_src),
6653 smb_fname_str_dbg(smb_fname_dst)));
6657 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6659 if (!smb_fname_dst->original_lcomp) {
6660 status = NT_STATUS_NO_MEMORY;
6664 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6665 attrs, replace_if_exists);
6667 close_file(req, fsp, NORMAL_CLOSE);
6669 if (!NT_STATUS_IS_OK(status)) {
6670 DEBUG(3, ("rename_internals_fsp returned %s for "
6671 "rename %s -> %s\n", nt_errstr(status),
6672 smb_fname_str_dbg(smb_fname_src),
6673 smb_fname_str_dbg(smb_fname_dst)));
6679 DEBUG(3,("rename_internals: doing rename on %s -> "
6680 "%s\n", smb_fname_str_dbg(smb_fname_src),
6681 smb_fname_str_dbg(smb_fname_src)));
6682 TALLOC_FREE(talloced);
6684 TALLOC_FREE(dir_hnd);
6686 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6687 status = map_nt_error_from_unix(errno);
6691 TALLOC_FREE(talloced);
6692 TALLOC_FREE(fname_src_dir);
6693 TALLOC_FREE(fname_src_mask);
6697 /****************************************************************************
6699 ****************************************************************************/
6701 void reply_mv(struct smb_request *req)
6703 connection_struct *conn = req->conn;
6705 char *newname = NULL;
6709 bool src_has_wcard = False;
6710 bool dest_has_wcard = False;
6711 TALLOC_CTX *ctx = talloc_tos();
6712 struct smb_filename *smb_fname_src = NULL;
6713 struct smb_filename *smb_fname_dst = NULL;
6714 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6715 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6716 bool stream_rename = false;
6718 START_PROFILE(SMBmv);
6721 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6725 attrs = SVAL(req->vwv+0, 0);
6727 p = (const char *)req->buf + 1;
6728 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6729 &status, &src_has_wcard);
6730 if (!NT_STATUS_IS_OK(status)) {
6731 reply_nterror(req, status);
6735 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6736 &status, &dest_has_wcard);
6737 if (!NT_STATUS_IS_OK(status)) {
6738 reply_nterror(req, status);
6742 if (!lp_posix_pathnames()) {
6743 /* The newname must begin with a ':' if the
6744 name contains a ':'. */
6745 if (strchr_m(name, ':')) {
6746 if (newname[0] != ':') {
6747 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6750 stream_rename = true;
6754 status = filename_convert(ctx,
6756 req->flags2 & FLAGS2_DFS_PATHNAMES,
6762 if (!NT_STATUS_IS_OK(status)) {
6763 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6764 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6765 ERRSRV, ERRbadpath);
6768 reply_nterror(req, status);
6772 status = filename_convert(ctx,
6774 req->flags2 & FLAGS2_DFS_PATHNAMES,
6780 if (!NT_STATUS_IS_OK(status)) {
6781 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6782 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6783 ERRSRV, ERRbadpath);
6786 reply_nterror(req, status);
6790 if (stream_rename) {
6791 /* smb_fname_dst->base_name must be the same as
6792 smb_fname_src->base_name. */
6793 TALLOC_FREE(smb_fname_dst->base_name);
6794 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6795 smb_fname_src->base_name);
6796 if (!smb_fname_dst->base_name) {
6797 reply_nterror(req, NT_STATUS_NO_MEMORY);
6802 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6803 smb_fname_str_dbg(smb_fname_dst)));
6805 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6806 attrs, False, src_has_wcard, dest_has_wcard,
6808 if (!NT_STATUS_IS_OK(status)) {
6809 if (open_was_deferred(req->sconn, req->mid)) {
6810 /* We have re-scheduled this call. */
6813 reply_nterror(req, status);
6817 reply_outbuf(req, 0, 0);
6819 TALLOC_FREE(smb_fname_src);
6820 TALLOC_FREE(smb_fname_dst);
6825 /*******************************************************************
6826 Copy a file as part of a reply_copy.
6827 ******************************************************************/
6830 * TODO: check error codes on all callers
6833 NTSTATUS copy_file(TALLOC_CTX *ctx,
6834 connection_struct *conn,
6835 struct smb_filename *smb_fname_src,
6836 struct smb_filename *smb_fname_dst,
6839 bool target_is_directory)
6841 struct smb_filename *smb_fname_dst_tmp = NULL;
6843 files_struct *fsp1,*fsp2;
6845 uint32 new_create_disposition;
6849 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6850 if (!NT_STATUS_IS_OK(status)) {
6855 * If the target is a directory, extract the last component from the
6856 * src filename and append it to the dst filename
6858 if (target_is_directory) {
6861 /* dest/target can't be a stream if it's a directory. */
6862 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6864 p = strrchr_m(smb_fname_src->base_name,'/');
6868 p = smb_fname_src->base_name;
6870 smb_fname_dst_tmp->base_name =
6871 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6873 if (!smb_fname_dst_tmp->base_name) {
6874 status = NT_STATUS_NO_MEMORY;
6879 status = vfs_file_exist(conn, smb_fname_src);
6880 if (!NT_STATUS_IS_OK(status)) {
6884 if (!target_is_directory && count) {
6885 new_create_disposition = FILE_OPEN;
6887 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6890 &new_create_disposition,
6893 status = NT_STATUS_INVALID_PARAMETER;
6898 /* Open the src file for reading. */
6899 status = SMB_VFS_CREATE_FILE(
6902 0, /* root_dir_fid */
6903 smb_fname_src, /* fname */
6904 FILE_GENERIC_READ, /* access_mask */
6905 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6906 FILE_OPEN, /* create_disposition*/
6907 0, /* create_options */
6908 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6909 INTERNAL_OPEN_ONLY, /* oplock_request */
6910 0, /* allocation_size */
6911 0, /* private_flags */
6917 if (!NT_STATUS_IS_OK(status)) {
6921 dosattrs = dos_mode(conn, smb_fname_src);
6923 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6924 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6927 /* Open the dst file for writing. */
6928 status = SMB_VFS_CREATE_FILE(
6931 0, /* root_dir_fid */
6932 smb_fname_dst, /* fname */
6933 FILE_GENERIC_WRITE, /* access_mask */
6934 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6935 new_create_disposition, /* create_disposition*/
6936 0, /* create_options */
6937 dosattrs, /* file_attributes */
6938 INTERNAL_OPEN_ONLY, /* oplock_request */
6939 0, /* allocation_size */
6940 0, /* private_flags */
6946 if (!NT_STATUS_IS_OK(status)) {
6947 close_file(NULL, fsp1, ERROR_CLOSE);
6951 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6952 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6954 DEBUG(0, ("error - vfs lseek returned error %s\n",
6956 status = map_nt_error_from_unix(errno);
6957 close_file(NULL, fsp1, ERROR_CLOSE);
6958 close_file(NULL, fsp2, ERROR_CLOSE);
6963 /* Do the actual copy. */
6964 if (smb_fname_src->st.st_ex_size) {
6965 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6970 close_file(NULL, fsp1, NORMAL_CLOSE);
6972 /* Ensure the modtime is set correctly on the destination file. */
6973 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6976 * As we are opening fsp1 read-only we only expect
6977 * an error on close on fsp2 if we are out of space.
6978 * Thus we don't look at the error return from the
6981 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6983 if (!NT_STATUS_IS_OK(status)) {
6987 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
6988 status = NT_STATUS_DISK_FULL;
6992 status = NT_STATUS_OK;
6995 TALLOC_FREE(smb_fname_dst_tmp);
6999 /****************************************************************************
7000 Reply to a file copy.
7001 ****************************************************************************/
7003 void reply_copy(struct smb_request *req)
7005 connection_struct *conn = req->conn;
7006 struct smb_filename *smb_fname_src = NULL;
7007 struct smb_filename *smb_fname_dst = NULL;
7008 char *fname_src = NULL;
7009 char *fname_dst = NULL;
7010 char *fname_src_mask = NULL;
7011 char *fname_src_dir = NULL;
7014 int error = ERRnoaccess;
7018 bool target_is_directory=False;
7019 bool source_has_wild = False;
7020 bool dest_has_wild = False;
7022 TALLOC_CTX *ctx = talloc_tos();
7024 START_PROFILE(SMBcopy);
7027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7031 tid2 = SVAL(req->vwv+0, 0);
7032 ofun = SVAL(req->vwv+1, 0);
7033 flags = SVAL(req->vwv+2, 0);
7035 p = (const char *)req->buf;
7036 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7037 &status, &source_has_wild);
7038 if (!NT_STATUS_IS_OK(status)) {
7039 reply_nterror(req, status);
7042 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7043 &status, &dest_has_wild);
7044 if (!NT_STATUS_IS_OK(status)) {
7045 reply_nterror(req, status);
7049 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7051 if (tid2 != conn->cnum) {
7052 /* can't currently handle inter share copies XXXX */
7053 DEBUG(3,("Rejecting inter-share copy\n"));
7054 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7058 status = filename_convert(ctx, conn,
7059 req->flags2 & FLAGS2_DFS_PATHNAMES,
7061 UCF_COND_ALLOW_WCARD_LCOMP,
7064 if (!NT_STATUS_IS_OK(status)) {
7065 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7066 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7067 ERRSRV, ERRbadpath);
7070 reply_nterror(req, status);
7074 status = filename_convert(ctx, conn,
7075 req->flags2 & FLAGS2_DFS_PATHNAMES,
7077 UCF_COND_ALLOW_WCARD_LCOMP,
7080 if (!NT_STATUS_IS_OK(status)) {
7081 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7082 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7083 ERRSRV, ERRbadpath);
7086 reply_nterror(req, status);
7090 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7092 if ((flags&1) && target_is_directory) {
7093 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7097 if ((flags&2) && !target_is_directory) {
7098 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7102 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7103 /* wants a tree copy! XXXX */
7104 DEBUG(3,("Rejecting tree copy\n"));
7105 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7109 /* Split up the directory from the filename/mask. */
7110 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7111 &fname_src_dir, &fname_src_mask);
7112 if (!NT_STATUS_IS_OK(status)) {
7113 reply_nterror(req, NT_STATUS_NO_MEMORY);
7118 * We should only check the mangled cache
7119 * here if unix_convert failed. This means
7120 * that the path in 'mask' doesn't exist
7121 * on the file system and so we need to look
7122 * for a possible mangle. This patch from
7123 * Tine Smukavec <valentin.smukavec@hermes.si>.
7125 if (!VALID_STAT(smb_fname_src->st) &&
7126 mangle_is_mangled(fname_src_mask, conn->params)) {
7127 char *new_mask = NULL;
7128 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7129 &new_mask, conn->params);
7131 /* Use demangled name if one was successfully found. */
7133 TALLOC_FREE(fname_src_mask);
7134 fname_src_mask = new_mask;
7138 if (!source_has_wild) {
7141 * Only one file needs to be copied. Append the mask back onto
7144 TALLOC_FREE(smb_fname_src->base_name);
7145 if (ISDOT(fname_src_dir)) {
7146 /* Ensure we use canonical names on open. */
7147 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7151 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7156 if (!smb_fname_src->base_name) {
7157 reply_nterror(req, NT_STATUS_NO_MEMORY);
7161 if (dest_has_wild) {
7162 char *fname_dst_mod = NULL;
7163 if (!resolve_wildcards(smb_fname_dst,
7164 smb_fname_src->base_name,
7165 smb_fname_dst->base_name,
7167 reply_nterror(req, NT_STATUS_NO_MEMORY);
7170 TALLOC_FREE(smb_fname_dst->base_name);
7171 smb_fname_dst->base_name = fname_dst_mod;
7174 status = check_name(conn, smb_fname_src->base_name);
7175 if (!NT_STATUS_IS_OK(status)) {
7176 reply_nterror(req, status);
7180 status = check_name(conn, smb_fname_dst->base_name);
7181 if (!NT_STATUS_IS_OK(status)) {
7182 reply_nterror(req, status);
7186 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7187 ofun, count, target_is_directory);
7189 if(!NT_STATUS_IS_OK(status)) {
7190 reply_nterror(req, status);
7196 struct smb_Dir *dir_hnd = NULL;
7197 const char *dname = NULL;
7198 char *talloced = NULL;
7202 * There is a wildcard that requires us to actually read the
7203 * src dir and copy each file matching the mask to the dst.
7204 * Right now streams won't be copied, but this could
7205 * presumably be added with a nested loop for reach dir entry.
7207 SMB_ASSERT(!smb_fname_src->stream_name);
7208 SMB_ASSERT(!smb_fname_dst->stream_name);
7210 smb_fname_src->stream_name = NULL;
7211 smb_fname_dst->stream_name = NULL;
7213 if (strequal(fname_src_mask,"????????.???")) {
7214 TALLOC_FREE(fname_src_mask);
7215 fname_src_mask = talloc_strdup(ctx, "*");
7216 if (!fname_src_mask) {
7217 reply_nterror(req, NT_STATUS_NO_MEMORY);
7222 status = check_name(conn, fname_src_dir);
7223 if (!NT_STATUS_IS_OK(status)) {
7224 reply_nterror(req, status);
7228 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7229 if (dir_hnd == NULL) {
7230 status = map_nt_error_from_unix(errno);
7231 reply_nterror(req, status);
7237 /* Iterate over the src dir copying each entry to the dst. */
7238 while ((dname = ReadDirName(dir_hnd, &offset,
7239 &smb_fname_src->st, &talloced))) {
7240 char *destname = NULL;
7242 if (ISDOT(dname) || ISDOTDOT(dname)) {
7243 TALLOC_FREE(talloced);
7247 if (!is_visible_file(conn, fname_src_dir, dname,
7248 &smb_fname_src->st, false)) {
7249 TALLOC_FREE(talloced);
7253 if(!mask_match(dname, fname_src_mask,
7254 conn->case_sensitive)) {
7255 TALLOC_FREE(talloced);
7259 error = ERRnoaccess;
7261 /* Get the src smb_fname struct setup. */
7262 TALLOC_FREE(smb_fname_src->base_name);
7263 if (ISDOT(fname_src_dir)) {
7264 /* Ensure we use canonical names on open. */
7265 smb_fname_src->base_name =
7266 talloc_asprintf(smb_fname_src, "%s",
7269 smb_fname_src->base_name =
7270 talloc_asprintf(smb_fname_src, "%s/%s",
7271 fname_src_dir, dname);
7274 if (!smb_fname_src->base_name) {
7275 TALLOC_FREE(dir_hnd);
7276 TALLOC_FREE(talloced);
7277 reply_nterror(req, NT_STATUS_NO_MEMORY);
7281 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7282 smb_fname_dst->base_name,
7284 TALLOC_FREE(talloced);
7288 TALLOC_FREE(dir_hnd);
7289 TALLOC_FREE(talloced);
7290 reply_nterror(req, NT_STATUS_NO_MEMORY);
7294 TALLOC_FREE(smb_fname_dst->base_name);
7295 smb_fname_dst->base_name = destname;
7297 status = check_name(conn, smb_fname_src->base_name);
7298 if (!NT_STATUS_IS_OK(status)) {
7299 TALLOC_FREE(dir_hnd);
7300 TALLOC_FREE(talloced);
7301 reply_nterror(req, status);
7305 status = check_name(conn, smb_fname_dst->base_name);
7306 if (!NT_STATUS_IS_OK(status)) {
7307 TALLOC_FREE(dir_hnd);
7308 TALLOC_FREE(talloced);
7309 reply_nterror(req, status);
7313 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7314 smb_fname_src->base_name,
7315 smb_fname_dst->base_name));
7317 status = copy_file(ctx, conn, smb_fname_src,
7318 smb_fname_dst, ofun, count,
7319 target_is_directory);
7320 if (NT_STATUS_IS_OK(status)) {
7324 TALLOC_FREE(talloced);
7326 TALLOC_FREE(dir_hnd);
7330 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7334 reply_outbuf(req, 1, 0);
7335 SSVAL(req->outbuf,smb_vwv0,count);
7337 TALLOC_FREE(smb_fname_src);
7338 TALLOC_FREE(smb_fname_dst);
7339 TALLOC_FREE(fname_src);
7340 TALLOC_FREE(fname_dst);
7341 TALLOC_FREE(fname_src_mask);
7342 TALLOC_FREE(fname_src_dir);
7344 END_PROFILE(SMBcopy);
7349 #define DBGC_CLASS DBGC_LOCKING
7351 /****************************************************************************
7352 Get a lock pid, dealing with large count requests.
7353 ****************************************************************************/
7355 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7356 bool large_file_format)
7358 if(!large_file_format)
7359 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7361 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7364 /****************************************************************************
7365 Get a lock count, dealing with large count requests.
7366 ****************************************************************************/
7368 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7369 bool large_file_format)
7373 if(!large_file_format) {
7374 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7377 #if defined(HAVE_LONGLONG)
7378 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7379 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7380 #else /* HAVE_LONGLONG */
7383 * NT4.x seems to be broken in that it sends large file (64 bit)
7384 * lockingX calls even if the CAP_LARGE_FILES was *not*
7385 * negotiated. For boxes without large unsigned ints truncate the
7386 * lock count by dropping the top 32 bits.
7389 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7390 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7391 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7392 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7393 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7396 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7397 #endif /* HAVE_LONGLONG */
7403 #if !defined(HAVE_LONGLONG)
7404 /****************************************************************************
7405 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7406 ****************************************************************************/
7408 static uint32 map_lock_offset(uint32 high, uint32 low)
7412 uint32 highcopy = high;
7415 * Try and find out how many significant bits there are in high.
7418 for(i = 0; highcopy; i++)
7422 * We use 31 bits not 32 here as POSIX
7423 * lock offsets may not be negative.
7426 mask = (~0) << (31 - i);
7429 return 0; /* Fail. */
7435 #endif /* !defined(HAVE_LONGLONG) */
7437 /****************************************************************************
7438 Get a lock offset, dealing with large offset requests.
7439 ****************************************************************************/
7441 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7442 bool large_file_format, bool *err)
7444 uint64_t offset = 0;
7448 if(!large_file_format) {
7449 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7452 #if defined(HAVE_LONGLONG)
7453 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7454 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7455 #else /* HAVE_LONGLONG */
7458 * NT4.x seems to be broken in that it sends large file (64 bit)
7459 * lockingX calls even if the CAP_LARGE_FILES was *not*
7460 * negotiated. For boxes without large unsigned ints mangle the
7461 * lock offset by mapping the top 32 bits onto the lower 32.
7464 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7465 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7466 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7469 if((new_low = map_lock_offset(high, low)) == 0) {
7471 return (uint64_t)-1;
7474 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7475 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7476 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7477 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7480 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7481 #endif /* HAVE_LONGLONG */
7487 NTSTATUS smbd_do_locking(struct smb_request *req,
7491 uint16_t num_ulocks,
7492 struct smbd_lock_element *ulocks,
7494 struct smbd_lock_element *locks,
7497 connection_struct *conn = req->conn;
7499 NTSTATUS status = NT_STATUS_OK;
7503 /* Data now points at the beginning of the list
7504 of smb_unlkrng structs */
7505 for(i = 0; i < (int)num_ulocks; i++) {
7506 struct smbd_lock_element *e = &ulocks[i];
7508 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7509 "pid %u, file %s\n",
7512 (unsigned int)e->smblctx,
7515 if (e->brltype != UNLOCK_LOCK) {
7516 /* this can only happen with SMB2 */
7517 return NT_STATUS_INVALID_PARAMETER;
7520 status = do_unlock(req->sconn->msg_ctx,
7527 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7528 nt_errstr(status)));
7530 if (!NT_STATUS_IS_OK(status)) {
7535 /* Setup the timeout in seconds. */
7537 if (!lp_blocking_locks(SNUM(conn))) {
7541 /* Data now points at the beginning of the list
7542 of smb_lkrng structs */
7544 for(i = 0; i < (int)num_locks; i++) {
7545 struct smbd_lock_element *e = &locks[i];
7547 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7548 "%llu, file %s timeout = %d\n",
7551 (unsigned long long)e->smblctx,
7555 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7556 struct blocking_lock_record *blr = NULL;
7558 if (num_locks > 1) {
7560 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7561 * if the lock vector contains one entry. When given mutliple cancel
7562 * requests in a single PDU we expect the server to return an
7563 * error. Windows servers seem to accept the request but only
7564 * cancel the first lock.
7565 * JRA - Do what Windows does (tm) :-).
7569 /* MS-CIFS (2.2.4.32.1) behavior. */
7570 return NT_STATUS_DOS(ERRDOS,
7571 ERRcancelviolation);
7573 /* Windows behavior. */
7575 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7576 "cancel request\n"));
7582 if (lp_blocking_locks(SNUM(conn))) {
7584 /* Schedule a message to ourselves to
7585 remove the blocking lock record and
7586 return the right error. */
7588 blr = blocking_lock_cancel_smb1(fsp,
7594 NT_STATUS_FILE_LOCK_CONFLICT);
7596 return NT_STATUS_DOS(
7598 ERRcancelviolation);
7601 /* Remove a matching pending lock. */
7602 status = do_lock_cancel(fsp,
7609 bool blocking_lock = timeout ? true : false;
7610 bool defer_lock = false;
7611 struct byte_range_lock *br_lck;
7612 uint64_t block_smblctx;
7614 br_lck = do_lock(req->sconn->msg_ctx,
7626 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7627 /* Windows internal resolution for blocking locks seems
7628 to be about 200ms... Don't wait for less than that. JRA. */
7629 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7630 timeout = lp_lock_spin_time();
7635 /* If a lock sent with timeout of zero would fail, and
7636 * this lock has been requested multiple times,
7637 * according to brl_lock_failed() we convert this
7638 * request to a blocking lock with a timeout of between
7639 * 150 - 300 milliseconds.
7641 * If lp_lock_spin_time() has been set to 0, we skip
7642 * this blocking retry and fail immediately.
7644 * Replacement for do_lock_spin(). JRA. */
7646 if (!req->sconn->using_smb2 &&
7647 br_lck && lp_blocking_locks(SNUM(conn)) &&
7648 lp_lock_spin_time() && !blocking_lock &&
7649 NT_STATUS_EQUAL((status),
7650 NT_STATUS_FILE_LOCK_CONFLICT))
7653 timeout = lp_lock_spin_time();
7656 if (br_lck && defer_lock) {
7658 * A blocking lock was requested. Package up
7659 * this smb into a queued request and push it
7660 * onto the blocking lock queue.
7662 if(push_blocking_lock_request(br_lck,
7673 TALLOC_FREE(br_lck);
7675 return NT_STATUS_OK;
7679 TALLOC_FREE(br_lck);
7682 if (!NT_STATUS_IS_OK(status)) {
7687 /* If any of the above locks failed, then we must unlock
7688 all of the previous locks (X/Open spec). */
7690 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7692 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7693 i = -1; /* we want to skip the for loop */
7697 * Ensure we don't do a remove on the lock that just failed,
7698 * as under POSIX rules, if we have a lock already there, we
7699 * will delete it (and we shouldn't) .....
7701 for(i--; i >= 0; i--) {
7702 struct smbd_lock_element *e = &locks[i];
7704 do_unlock(req->sconn->msg_ctx,
7714 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d num_ulocks=%d\n",
7715 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks, num_ulocks));
7717 return NT_STATUS_OK;
7720 /****************************************************************************
7721 Reply to a lockingX request.
7722 ****************************************************************************/
7724 void reply_lockingX(struct smb_request *req)
7726 connection_struct *conn = req->conn;
7728 unsigned char locktype;
7729 unsigned char oplocklevel;
7734 const uint8_t *data;
7735 bool large_file_format;
7737 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7738 struct smbd_lock_element *ulocks;
7739 struct smbd_lock_element *locks;
7742 START_PROFILE(SMBlockingX);
7745 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7746 END_PROFILE(SMBlockingX);
7750 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7751 locktype = CVAL(req->vwv+3, 0);
7752 oplocklevel = CVAL(req->vwv+3, 1);
7753 num_ulocks = SVAL(req->vwv+6, 0);
7754 num_locks = SVAL(req->vwv+7, 0);
7755 lock_timeout = IVAL(req->vwv+4, 0);
7756 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7758 if (!check_fsp(conn, req, fsp)) {
7759 END_PROFILE(SMBlockingX);
7765 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7766 /* we don't support these - and CANCEL_LOCK makes w2k
7767 and XP reboot so I don't really want to be
7768 compatible! (tridge) */
7769 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7770 END_PROFILE(SMBlockingX);
7774 /* Check if this is an oplock break on a file
7775 we have granted an oplock on.
7777 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7778 /* Client can insist on breaking to none. */
7779 bool break_to_none = (oplocklevel == 0);
7782 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7783 "for %s\n", (unsigned int)oplocklevel,
7784 fsp_fnum_dbg(fsp)));
7787 * Make sure we have granted an exclusive or batch oplock on
7791 if (fsp->oplock_type == 0) {
7793 /* The Samba4 nbench simulator doesn't understand
7794 the difference between break to level2 and break
7795 to none from level2 - it sends oplock break
7796 replies in both cases. Don't keep logging an error
7797 message here - just ignore it. JRA. */
7799 DEBUG(5,("reply_lockingX: Error : oplock break from "
7800 "client for %s (oplock=%d) and no "
7801 "oplock granted on this file (%s).\n",
7802 fsp_fnum_dbg(fsp), fsp->oplock_type,
7805 /* if this is a pure oplock break request then don't
7807 if (num_locks == 0 && num_ulocks == 0) {
7808 END_PROFILE(SMBlockingX);
7811 END_PROFILE(SMBlockingX);
7812 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7817 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7819 result = remove_oplock(fsp);
7821 result = downgrade_oplock(fsp);
7825 DEBUG(0, ("reply_lockingX: error in removing "
7826 "oplock on file %s\n", fsp_str_dbg(fsp)));
7827 /* Hmmm. Is this panic justified? */
7828 smb_panic("internal tdb error");
7831 reply_to_oplock_break_requests(fsp);
7833 /* if this is a pure oplock break request then don't send a
7835 if (num_locks == 0 && num_ulocks == 0) {
7836 /* Sanity check - ensure a pure oplock break is not a
7838 if(CVAL(req->vwv+0, 0) != 0xff)
7839 DEBUG(0,("reply_lockingX: Error : pure oplock "
7840 "break is a chained %d request !\n",
7841 (unsigned int)CVAL(req->vwv+0, 0)));
7842 END_PROFILE(SMBlockingX);
7848 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7849 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7850 END_PROFILE(SMBlockingX);
7854 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7855 if (ulocks == NULL) {
7856 reply_nterror(req, NT_STATUS_NO_MEMORY);
7857 END_PROFILE(SMBlockingX);
7861 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7862 if (locks == NULL) {
7863 reply_nterror(req, NT_STATUS_NO_MEMORY);
7864 END_PROFILE(SMBlockingX);
7868 /* Data now points at the beginning of the list
7869 of smb_unlkrng structs */
7870 for(i = 0; i < (int)num_ulocks; i++) {
7871 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7872 ulocks[i].count = get_lock_count(data, i, large_file_format);
7873 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7874 ulocks[i].brltype = UNLOCK_LOCK;
7877 * There is no error code marked "stupid client bug".... :-).
7880 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7881 END_PROFILE(SMBlockingX);
7886 /* Now do any requested locks */
7887 data += ((large_file_format ? 20 : 10)*num_ulocks);
7889 /* Data now points at the beginning of the list
7890 of smb_lkrng structs */
7892 for(i = 0; i < (int)num_locks; i++) {
7893 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7894 locks[i].count = get_lock_count(data, i, large_file_format);
7895 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7897 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7898 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7899 locks[i].brltype = PENDING_READ_LOCK;
7901 locks[i].brltype = READ_LOCK;
7904 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7905 locks[i].brltype = PENDING_WRITE_LOCK;
7907 locks[i].brltype = WRITE_LOCK;
7912 * There is no error code marked "stupid client bug".... :-).
7915 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7916 END_PROFILE(SMBlockingX);
7921 status = smbd_do_locking(req, fsp,
7922 locktype, lock_timeout,
7926 if (!NT_STATUS_IS_OK(status)) {
7927 END_PROFILE(SMBlockingX);
7928 reply_nterror(req, status);
7932 END_PROFILE(SMBlockingX);
7936 reply_outbuf(req, 2, 0);
7937 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
7938 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
7940 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
7941 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
7943 END_PROFILE(SMBlockingX);
7947 #define DBGC_CLASS DBGC_ALL
7949 /****************************************************************************
7950 Reply to a SMBreadbmpx (read block multiplex) request.
7951 Always reply with an error, if someone has a platform really needs this,
7952 please contact vl@samba.org
7953 ****************************************************************************/
7955 void reply_readbmpx(struct smb_request *req)
7957 START_PROFILE(SMBreadBmpx);
7958 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7959 END_PROFILE(SMBreadBmpx);
7963 /****************************************************************************
7964 Reply to a SMBreadbs (read block multiplex secondary) request.
7965 Always reply with an error, if someone has a platform really needs this,
7966 please contact vl@samba.org
7967 ****************************************************************************/
7969 void reply_readbs(struct smb_request *req)
7971 START_PROFILE(SMBreadBs);
7972 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7973 END_PROFILE(SMBreadBs);
7977 /****************************************************************************
7978 Reply to a SMBsetattrE.
7979 ****************************************************************************/
7981 void reply_setattrE(struct smb_request *req)
7983 connection_struct *conn = req->conn;
7984 struct smb_file_time ft;
7988 START_PROFILE(SMBsetattrE);
7992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7996 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7998 if(!fsp || (fsp->conn != conn)) {
7999 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8004 * Convert the DOS times into unix times.
8007 ft.atime = convert_time_t_to_timespec(
8008 srv_make_unix_date2(req->vwv+3));
8009 ft.mtime = convert_time_t_to_timespec(
8010 srv_make_unix_date2(req->vwv+5));
8011 ft.create_time = convert_time_t_to_timespec(
8012 srv_make_unix_date2(req->vwv+1));
8014 reply_outbuf(req, 0, 0);
8017 * Patch from Ray Frush <frush@engr.colostate.edu>
8018 * Sometimes times are sent as zero - ignore them.
8021 /* Ensure we have a valid stat struct for the source. */
8022 status = vfs_stat_fsp(fsp);
8023 if (!NT_STATUS_IS_OK(status)) {
8024 reply_nterror(req, status);
8028 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8029 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8033 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8034 if (!NT_STATUS_IS_OK(status)) {
8035 reply_nterror(req, status);
8039 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8042 (unsigned int)ft.atime.tv_sec,
8043 (unsigned int)ft.mtime.tv_sec,
8044 (unsigned int)ft.create_time.tv_sec
8047 END_PROFILE(SMBsetattrE);
8052 /* Back from the dead for OS/2..... JRA. */
8054 /****************************************************************************
8055 Reply to a SMBwritebmpx (write block multiplex primary) request.
8056 Always reply with an error, if someone has a platform really needs this,
8057 please contact vl@samba.org
8058 ****************************************************************************/
8060 void reply_writebmpx(struct smb_request *req)
8062 START_PROFILE(SMBwriteBmpx);
8063 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8064 END_PROFILE(SMBwriteBmpx);
8068 /****************************************************************************
8069 Reply to a SMBwritebs (write block multiplex secondary) request.
8070 Always reply with an error, if someone has a platform really needs this,
8071 please contact vl@samba.org
8072 ****************************************************************************/
8074 void reply_writebs(struct smb_request *req)
8076 START_PROFILE(SMBwriteBs);
8077 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8078 END_PROFILE(SMBwriteBs);
8082 /****************************************************************************
8083 Reply to a SMBgetattrE.
8084 ****************************************************************************/
8086 void reply_getattrE(struct smb_request *req)
8088 connection_struct *conn = req->conn;
8091 struct timespec create_ts;
8093 START_PROFILE(SMBgetattrE);
8096 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8097 END_PROFILE(SMBgetattrE);
8101 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8103 if(!fsp || (fsp->conn != conn)) {
8104 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8105 END_PROFILE(SMBgetattrE);
8109 /* Do an fstat on this file */
8111 reply_nterror(req, map_nt_error_from_unix(errno));
8112 END_PROFILE(SMBgetattrE);
8116 mode = dos_mode(conn, fsp->fsp_name);
8119 * Convert the times into dos times. Set create
8120 * date to be last modify date as UNIX doesn't save
8124 reply_outbuf(req, 11, 0);
8126 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8127 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8128 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8129 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8130 /* Should we check pending modtime here ? JRA */
8131 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8132 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8134 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8135 SIVAL(req->outbuf, smb_vwv6, 0);
8136 SIVAL(req->outbuf, smb_vwv8, 0);
8138 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8139 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8140 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8142 SSVAL(req->outbuf,smb_vwv10, mode);
8144 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8146 END_PROFILE(SMBgetattrE);