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 "rpc_client/cli_spoolss.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_server/rpc_ncacn_np.h"
38 #include "libcli/security/security.h"
39 #include "libsmb/nmblib.h"
41 #include "smbprofile.h"
42 #include "../lib/tsocket/tsocket.h"
44 /****************************************************************************
45 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
46 path or anything including wildcards.
47 We're assuming here that '/' is not the second byte in any multibyte char
48 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
50 ****************************************************************************/
52 /* Custom version for processing POSIX paths. */
53 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
55 static NTSTATUS check_path_syntax_internal(char *path,
57 bool *p_last_component_contains_wcard)
61 NTSTATUS ret = NT_STATUS_OK;
62 bool start_of_name_component = True;
63 bool stream_started = false;
65 *p_last_component_contains_wcard = False;
72 return NT_STATUS_OBJECT_NAME_INVALID;
75 return NT_STATUS_OBJECT_NAME_INVALID;
77 if (strchr_m(&s[1], ':')) {
78 return NT_STATUS_OBJECT_NAME_INVALID;
84 if ((*s == ':') && !posix_path && !stream_started) {
85 if (*p_last_component_contains_wcard) {
86 return NT_STATUS_OBJECT_NAME_INVALID;
88 /* Stream names allow more characters than file names.
89 We're overloading posix_path here to allow a wider
90 range of characters. If stream_started is true this
91 is still a Windows path even if posix_path is true.
94 stream_started = true;
95 start_of_name_component = false;
99 return NT_STATUS_OBJECT_NAME_INVALID;
103 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
105 * Safe to assume is not the second part of a mb char
106 * as this is handled below.
108 /* Eat multiple '/' or '\\' */
109 while (IS_PATH_SEP(*s,posix_path)) {
112 if ((d != path) && (*s != '\0')) {
113 /* We only care about non-leading or trailing '/' or '\\' */
117 start_of_name_component = True;
119 *p_last_component_contains_wcard = False;
123 if (start_of_name_component) {
124 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
125 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
128 * No mb char starts with '.' so we're safe checking the directory separator here.
131 /* If we just added a '/' - delete it */
132 if ((d > path) && (*(d-1) == '/')) {
137 /* Are we at the start ? Can't go back further if so. */
139 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
142 /* Go back one level... */
143 /* We know this is safe as '/' cannot be part of a mb sequence. */
144 /* NOTE - if this assumption is invalid we are not in good shape... */
145 /* Decrement d first as d points to the *next* char to write into. */
146 for (d--; d > path; d--) {
150 s += 2; /* Else go past the .. */
151 /* We're still at the start of a name component, just the previous one. */
154 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
166 if (*s <= 0x1f || *s == '|') {
167 return NT_STATUS_OBJECT_NAME_INVALID;
175 *p_last_component_contains_wcard = True;
184 /* Get the size of the next MB character. */
185 next_codepoint(s,&siz);
203 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
205 return NT_STATUS_INVALID_PARAMETER;
208 start_of_name_component = False;
216 /****************************************************************************
217 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
218 No wildcards allowed.
219 ****************************************************************************/
221 NTSTATUS check_path_syntax(char *path)
224 return check_path_syntax_internal(path, False, &ignore);
227 /****************************************************************************
228 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
229 Wildcards allowed - p_contains_wcard returns true if the last component contained
231 ****************************************************************************/
233 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
235 return check_path_syntax_internal(path, False, p_contains_wcard);
238 /****************************************************************************
239 Check the path for a POSIX client.
240 We're assuming here that '/' is not the second byte in any multibyte char
241 set (a safe assumption).
242 ****************************************************************************/
244 NTSTATUS check_path_syntax_posix(char *path)
247 return check_path_syntax_internal(path, True, &ignore);
250 /****************************************************************************
251 Pull a string and check the path allowing a wilcard - provide for error return.
252 ****************************************************************************/
254 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
255 const char *base_ptr,
262 bool *contains_wcard)
268 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
272 *err = NT_STATUS_INVALID_PARAMETER;
276 *contains_wcard = False;
278 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
280 * For a DFS path the function parse_dfs_path()
281 * will do the path processing, just make a copy.
287 if (lp_posix_pathnames()) {
288 *err = check_path_syntax_posix(*pp_dest);
290 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
296 /****************************************************************************
297 Pull a string and check the path - provide for error return.
298 ****************************************************************************/
300 size_t srvstr_get_path(TALLOC_CTX *ctx,
301 const char *base_ptr,
310 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
311 src_len, flags, err, &ignore);
314 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
315 char **pp_dest, const char *src, int flags,
316 NTSTATUS *err, bool *contains_wcard)
318 return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf, req->flags2,
319 pp_dest, src, smbreq_bufrem(req, src),
320 flags, err, contains_wcard);
323 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
324 char **pp_dest, const char *src, int flags,
328 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
329 flags, err, &ignore);
332 /****************************************************************************
333 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
334 ****************************************************************************/
336 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
339 if ((fsp == NULL) || (conn == NULL)) {
340 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
343 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
344 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
350 /****************************************************************************
351 Check if we have a correct fsp pointing to a file.
352 ****************************************************************************/
354 bool check_fsp(connection_struct *conn, struct smb_request *req,
357 if (!check_fsp_open(conn, req, fsp)) {
360 if (fsp->is_directory) {
361 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
364 if (fsp->fh->fd == -1) {
365 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
368 fsp->num_smb_operations++;
372 /****************************************************************************
373 Check if we have a correct fsp pointing to a quota fake file. Replacement for
374 the CHECK_NTQUOTA_HANDLE_OK macro.
375 ****************************************************************************/
377 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
380 if (!check_fsp_open(conn, req, fsp)) {
384 if (fsp->is_directory) {
388 if (fsp->fake_file_handle == NULL) {
392 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
396 if (fsp->fake_file_handle->private_data == NULL) {
403 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
404 const char *name, int name_type)
407 char *trim_name_type;
408 const char *retarget_parm;
411 int retarget_type = 0x20;
412 int retarget_port = 139;
413 struct sockaddr_storage retarget_addr;
414 struct sockaddr_in *in_addr;
418 if (get_socket_port(sconn->sock) != 139) {
422 trim_name = talloc_strdup(talloc_tos(), name);
423 if (trim_name == NULL) {
426 trim_char(trim_name, ' ', ' ');
428 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
430 if (trim_name_type == NULL) {
434 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
435 trim_name_type, NULL);
436 if (retarget_parm == NULL) {
437 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
440 if (retarget_parm == NULL) {
444 retarget = talloc_strdup(trim_name, retarget_parm);
445 if (retarget == NULL) {
449 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
451 p = strchr(retarget, ':');
454 retarget_port = atoi(p);
457 p = strchr_m(retarget, '#');
460 if (sscanf(p, "%x", &retarget_type) != 1) {
465 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
467 DEBUG(10, ("could not resolve %s\n", retarget));
471 if (retarget_addr.ss_family != AF_INET) {
472 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
476 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
478 _smb_setlen(outbuf, 6);
479 SCVAL(outbuf, 0, 0x84);
480 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
481 *(uint16_t *)(outbuf+8) = htons(retarget_port);
483 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
485 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
491 TALLOC_FREE(trim_name);
495 static void reply_called_name_not_present(char *outbuf)
497 smb_setlen(outbuf, 1);
498 SCVAL(outbuf, 0, 0x83);
499 SCVAL(outbuf, 4, 0x82);
502 /****************************************************************************
503 Reply to a (netbios-level) special message.
504 ****************************************************************************/
506 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
508 int msg_type = CVAL(inbuf,0);
509 int msg_flags = CVAL(inbuf,1);
511 * We only really use 4 bytes of the outbuf, but for the smb_setlen
512 * calculation & friends (srv_send_smb uses that) we need the full smb
515 char outbuf[smb_size];
517 memset(outbuf, '\0', sizeof(outbuf));
519 smb_setlen(outbuf,0);
522 case NBSSrequest: /* session request */
524 /* inbuf_size is guarenteed to be at least 4. */
526 int name_type1, name_type2;
527 int name_len1, name_len2;
531 if (sconn->nbt.got_session) {
532 exit_server_cleanly("multiple session request not permitted");
535 SCVAL(outbuf,0,NBSSpositive);
538 /* inbuf_size is guaranteed to be at least 4. */
539 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
540 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
541 DEBUG(0,("Invalid name length in session request\n"));
542 reply_called_name_not_present(outbuf);
545 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
546 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
547 DEBUG(0,("Invalid name length in session request\n"));
548 reply_called_name_not_present(outbuf);
552 name_type1 = name_extract((unsigned char *)inbuf,
553 inbuf_size,(unsigned int)4,name1);
554 name_type2 = name_extract((unsigned char *)inbuf,
555 inbuf_size,(unsigned int)(4 + name_len1),name2);
557 if (name_type1 == -1 || name_type2 == -1) {
558 DEBUG(0,("Invalid name type in session request\n"));
559 reply_called_name_not_present(outbuf);
563 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
564 name1, name_type1, name2, name_type2));
566 if (netbios_session_retarget(sconn, name1, name_type1)) {
567 exit_server_cleanly("retargeted client");
571 * Windows NT/2k uses "*SMBSERVER" and XP uses
572 * "*SMBSERV" arrggg!!!
574 if (strequal(name1, "*SMBSERVER ")
575 || strequal(name1, "*SMBSERV ")) {
578 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
581 exit_server_cleanly("could not allocate raddr");
584 fstrcpy(name1, raddr);
587 set_local_machine_name(name1, True);
588 set_remote_machine_name(name2, True);
590 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
591 get_local_machine_name(), get_remote_machine_name(),
594 if (name_type2 == 'R') {
595 /* We are being asked for a pathworks session ---
597 reply_called_name_not_present(outbuf);
601 /* only add the client's machine name to the list
602 of possibly valid usernames if we are operating
603 in share mode security */
604 if (lp_security() == SEC_SHARE) {
605 add_session_user(sconn, get_remote_machine_name());
608 reload_services(sconn->msg_ctx, sconn->sock, True);
611 sconn->nbt.got_session = true;
615 case 0x89: /* session keepalive request
616 (some old clients produce this?) */
617 SCVAL(outbuf,0,NBSSkeepalive);
621 case NBSSpositive: /* positive session response */
622 case NBSSnegative: /* negative session response */
623 case NBSSretarget: /* retarget session response */
624 DEBUG(0,("Unexpected session response\n"));
627 case NBSSkeepalive: /* session keepalive */
632 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
633 msg_type, msg_flags));
635 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
637 if (CVAL(outbuf, 0) != 0x82) {
638 exit_server_cleanly("invalid netbios session");
643 /****************************************************************************
645 conn POINTER CAN BE NULL HERE !
646 ****************************************************************************/
648 void reply_tcon(struct smb_request *req)
650 connection_struct *conn = req->conn;
652 char *service_buf = NULL;
653 char *password = NULL;
658 DATA_BLOB password_blob;
659 TALLOC_CTX *ctx = talloc_tos();
660 struct smbd_server_connection *sconn = req->sconn;
662 START_PROFILE(SMBtcon);
664 if (req->buflen < 4) {
665 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
666 END_PROFILE(SMBtcon);
670 p = (const char *)req->buf + 1;
671 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
673 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
675 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
678 if (service_buf == NULL || password == NULL || dev == NULL) {
679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
680 END_PROFILE(SMBtcon);
683 p = strrchr_m(service_buf,'\\');
687 service = service_buf;
690 password_blob = data_blob(password, pwlen+1);
692 conn = make_connection(sconn,service,password_blob,dev,
693 req->vuid,&nt_status);
696 data_blob_clear_free(&password_blob);
699 reply_nterror(req, nt_status);
700 END_PROFILE(SMBtcon);
704 reply_outbuf(req, 2, 0);
705 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
706 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
707 SSVAL(req->outbuf,smb_tid,conn->cnum);
709 DEBUG(3,("tcon service=%s cnum=%d\n",
710 service, conn->cnum));
712 END_PROFILE(SMBtcon);
716 /****************************************************************************
717 Reply to a tcon and X.
718 conn POINTER CAN BE NULL HERE !
719 ****************************************************************************/
721 void reply_tcon_and_X(struct smb_request *req)
723 connection_struct *conn = req->conn;
724 const char *service = NULL;
726 TALLOC_CTX *ctx = talloc_tos();
727 /* what the cleint thinks the device is */
728 char *client_devicetype = NULL;
729 /* what the server tells the client the share represents */
730 const char *server_devicetype;
736 struct smbd_server_connection *sconn = req->sconn;
738 START_PROFILE(SMBtconX);
741 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
742 END_PROFILE(SMBtconX);
746 passlen = SVAL(req->vwv+3, 0);
747 tcon_flags = SVAL(req->vwv+2, 0);
749 /* we might have to close an old one */
750 if ((tcon_flags & 0x1) && conn) {
751 close_cnum(conn,req->vuid);
756 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
757 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
758 END_PROFILE(SMBtconX);
762 if (sconn->smb1.negprot.encrypted_passwords) {
763 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
764 if (lp_security() == SEC_SHARE) {
766 * Security = share always has a pad byte
767 * after the password.
769 p = (const char *)req->buf + passlen + 1;
771 p = (const char *)req->buf + passlen;
774 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
775 /* Ensure correct termination */
776 password.data[passlen]=0;
777 p = (const char *)req->buf + passlen + 1;
780 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
783 data_blob_clear_free(&password);
784 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
785 END_PROFILE(SMBtconX);
790 * the service name can be either: \\server\share
791 * or share directly like on the DELL PowerVault 705
794 q = strchr_m(path+2,'\\');
796 data_blob_clear_free(&password);
797 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
798 END_PROFILE(SMBtconX);
806 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
807 &client_devicetype, p,
808 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
810 if (client_devicetype == NULL) {
811 data_blob_clear_free(&password);
812 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
813 END_PROFILE(SMBtconX);
817 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
819 conn = make_connection(sconn, service, password, client_devicetype,
820 req->vuid, &nt_status);
823 data_blob_clear_free(&password);
826 reply_nterror(req, nt_status);
827 END_PROFILE(SMBtconX);
832 server_devicetype = "IPC";
833 else if ( IS_PRINT(conn) )
834 server_devicetype = "LPT1:";
836 server_devicetype = "A:";
838 if (get_Protocol() < PROTOCOL_NT1) {
839 reply_outbuf(req, 2, 0);
840 if (message_push_string(&req->outbuf, server_devicetype,
841 STR_TERMINATE|STR_ASCII) == -1) {
842 reply_nterror(req, NT_STATUS_NO_MEMORY);
843 END_PROFILE(SMBtconX);
847 /* NT sets the fstype of IPC$ to the null string */
848 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
850 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
851 /* Return permissions. */
855 reply_outbuf(req, 7, 0);
858 perm1 = FILE_ALL_ACCESS;
859 perm2 = FILE_ALL_ACCESS;
861 perm1 = conn->share_access;
864 SIVAL(req->outbuf, smb_vwv3, perm1);
865 SIVAL(req->outbuf, smb_vwv5, perm2);
867 reply_outbuf(req, 3, 0);
870 if ((message_push_string(&req->outbuf, server_devicetype,
871 STR_TERMINATE|STR_ASCII) == -1)
872 || (message_push_string(&req->outbuf, fstype,
873 STR_TERMINATE) == -1)) {
874 reply_nterror(req, NT_STATUS_NO_MEMORY);
875 END_PROFILE(SMBtconX);
879 /* what does setting this bit do? It is set by NT4 and
880 may affect the ability to autorun mounted cdroms */
881 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
882 (lp_csc_policy(SNUM(conn)) << 2));
884 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
885 DEBUG(2,("Serving %s as a Dfs root\n",
886 lp_servicename(SNUM(conn)) ));
887 SSVAL(req->outbuf, smb_vwv2,
888 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
893 DEBUG(3,("tconX service=%s \n",
896 /* set the incoming and outgoing tid to the just created one */
897 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
898 SSVAL(req->outbuf,smb_tid,conn->cnum);
900 END_PROFILE(SMBtconX);
902 req->tid = conn->cnum;
907 /****************************************************************************
908 Reply to an unknown type.
909 ****************************************************************************/
911 void reply_unknown_new(struct smb_request *req, uint8 type)
913 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
914 smb_fn_name(type), type, type));
915 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
919 /****************************************************************************
921 conn POINTER CAN BE NULL HERE !
922 ****************************************************************************/
924 void reply_ioctl(struct smb_request *req)
926 connection_struct *conn = req->conn;
933 START_PROFILE(SMBioctl);
936 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
937 END_PROFILE(SMBioctl);
941 device = SVAL(req->vwv+1, 0);
942 function = SVAL(req->vwv+2, 0);
943 ioctl_code = (device << 16) + function;
945 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
947 switch (ioctl_code) {
948 case IOCTL_QUERY_JOB_INFO:
952 reply_force_doserror(req, ERRSRV, ERRnosupport);
953 END_PROFILE(SMBioctl);
957 reply_outbuf(req, 8, replysize+1);
958 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
959 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
960 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
961 p = smb_buf(req->outbuf);
962 memset(p, '\0', replysize+1); /* valgrind-safe. */
963 p += 1; /* Allow for alignment */
965 switch (ioctl_code) {
966 case IOCTL_QUERY_JOB_INFO:
968 files_struct *fsp = file_fsp(
969 req, SVAL(req->vwv+0, 0));
971 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
972 END_PROFILE(SMBioctl);
976 if (fsp->print_file) {
977 SSVAL(p, 0, fsp->print_file->rap_jobid);
981 srvstr_push((char *)req->outbuf, req->flags2, p+2,
982 lp_netbios_name(), 15,
983 STR_TERMINATE|STR_ASCII);
985 srvstr_push((char *)req->outbuf, req->flags2,
986 p+18, lp_servicename(SNUM(conn)),
987 13, STR_TERMINATE|STR_ASCII);
995 END_PROFILE(SMBioctl);
999 /****************************************************************************
1000 Strange checkpath NTSTATUS mapping.
1001 ****************************************************************************/
1003 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1005 /* Strange DOS error code semantics only for checkpath... */
1006 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1007 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1008 /* We need to map to ERRbadpath */
1009 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1015 /****************************************************************************
1016 Reply to a checkpath.
1017 ****************************************************************************/
1019 void reply_checkpath(struct smb_request *req)
1021 connection_struct *conn = req->conn;
1022 struct smb_filename *smb_fname = NULL;
1025 TALLOC_CTX *ctx = talloc_tos();
1027 START_PROFILE(SMBcheckpath);
1029 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1030 STR_TERMINATE, &status);
1032 if (!NT_STATUS_IS_OK(status)) {
1033 status = map_checkpath_error(req->flags2, status);
1034 reply_nterror(req, status);
1035 END_PROFILE(SMBcheckpath);
1039 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1041 status = filename_convert(ctx,
1043 req->flags2 & FLAGS2_DFS_PATHNAMES,
1049 if (!NT_STATUS_IS_OK(status)) {
1050 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1051 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1052 ERRSRV, ERRbadpath);
1053 END_PROFILE(SMBcheckpath);
1059 if (!VALID_STAT(smb_fname->st) &&
1060 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1061 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1062 smb_fname_str_dbg(smb_fname), strerror(errno)));
1063 status = map_nt_error_from_unix(errno);
1067 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1068 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1069 ERRDOS, ERRbadpath);
1073 reply_outbuf(req, 0, 0);
1076 /* We special case this - as when a Windows machine
1077 is parsing a path is steps through the components
1078 one at a time - if a component fails it expects
1079 ERRbadpath, not ERRbadfile.
1081 status = map_checkpath_error(req->flags2, status);
1082 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1084 * Windows returns different error codes if
1085 * the parent directory is valid but not the
1086 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1087 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1088 * if the path is invalid.
1090 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1091 ERRDOS, ERRbadpath);
1095 reply_nterror(req, status);
1098 TALLOC_FREE(smb_fname);
1099 END_PROFILE(SMBcheckpath);
1103 /****************************************************************************
1105 ****************************************************************************/
1107 void reply_getatr(struct smb_request *req)
1109 connection_struct *conn = req->conn;
1110 struct smb_filename *smb_fname = NULL;
1117 TALLOC_CTX *ctx = talloc_tos();
1118 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1120 START_PROFILE(SMBgetatr);
1122 p = (const char *)req->buf + 1;
1123 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1124 if (!NT_STATUS_IS_OK(status)) {
1125 reply_nterror(req, status);
1129 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1130 under WfWg - weird! */
1131 if (*fname == '\0') {
1132 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1133 if (!CAN_WRITE(conn)) {
1134 mode |= FILE_ATTRIBUTE_READONLY;
1139 status = filename_convert(ctx,
1141 req->flags2 & FLAGS2_DFS_PATHNAMES,
1146 if (!NT_STATUS_IS_OK(status)) {
1147 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1148 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1149 ERRSRV, ERRbadpath);
1152 reply_nterror(req, status);
1155 if (!VALID_STAT(smb_fname->st) &&
1156 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1157 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1158 smb_fname_str_dbg(smb_fname),
1160 reply_nterror(req, map_nt_error_from_unix(errno));
1164 mode = dos_mode(conn, smb_fname);
1165 size = smb_fname->st.st_ex_size;
1167 if (ask_sharemode) {
1168 struct timespec write_time_ts;
1169 struct file_id fileid;
1171 ZERO_STRUCT(write_time_ts);
1172 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1173 get_file_infos(fileid, 0, NULL, &write_time_ts);
1174 if (!null_timespec(write_time_ts)) {
1175 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1179 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1180 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1185 reply_outbuf(req, 10, 0);
1187 SSVAL(req->outbuf,smb_vwv0,mode);
1188 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1189 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1191 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1193 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1195 if (get_Protocol() >= PROTOCOL_NT1) {
1196 SSVAL(req->outbuf, smb_flg2,
1197 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1200 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1201 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1204 TALLOC_FREE(smb_fname);
1206 END_PROFILE(SMBgetatr);
1210 /****************************************************************************
1212 ****************************************************************************/
1214 void reply_setatr(struct smb_request *req)
1216 struct smb_file_time ft;
1217 connection_struct *conn = req->conn;
1218 struct smb_filename *smb_fname = NULL;
1224 TALLOC_CTX *ctx = talloc_tos();
1226 START_PROFILE(SMBsetatr);
1231 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1235 p = (const char *)req->buf + 1;
1236 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1237 if (!NT_STATUS_IS_OK(status)) {
1238 reply_nterror(req, status);
1242 status = filename_convert(ctx,
1244 req->flags2 & FLAGS2_DFS_PATHNAMES,
1249 if (!NT_STATUS_IS_OK(status)) {
1250 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1251 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1252 ERRSRV, ERRbadpath);
1255 reply_nterror(req, status);
1259 if (smb_fname->base_name[0] == '.' &&
1260 smb_fname->base_name[1] == '\0') {
1262 * Not sure here is the right place to catch this
1263 * condition. Might be moved to somewhere else later -- vl
1265 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1269 mode = SVAL(req->vwv+0, 0);
1270 mtime = srv_make_unix_date3(req->vwv+1);
1272 ft.mtime = convert_time_t_to_timespec(mtime);
1273 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1274 if (!NT_STATUS_IS_OK(status)) {
1275 reply_nterror(req, status);
1279 if (mode != FILE_ATTRIBUTE_NORMAL) {
1280 if (VALID_STAT_OF_DIR(smb_fname->st))
1281 mode |= FILE_ATTRIBUTE_DIRECTORY;
1283 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1285 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1287 reply_nterror(req, map_nt_error_from_unix(errno));
1292 reply_outbuf(req, 0, 0);
1294 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1297 TALLOC_FREE(smb_fname);
1298 END_PROFILE(SMBsetatr);
1302 /****************************************************************************
1304 ****************************************************************************/
1306 void reply_dskattr(struct smb_request *req)
1308 connection_struct *conn = req->conn;
1309 uint64_t dfree,dsize,bsize;
1310 START_PROFILE(SMBdskattr);
1312 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1313 reply_nterror(req, map_nt_error_from_unix(errno));
1314 END_PROFILE(SMBdskattr);
1318 reply_outbuf(req, 5, 0);
1320 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1321 double total_space, free_space;
1322 /* we need to scale this to a number that DOS6 can handle. We
1323 use floating point so we can handle large drives on systems
1324 that don't have 64 bit integers
1326 we end up displaying a maximum of 2G to DOS systems
1328 total_space = dsize * (double)bsize;
1329 free_space = dfree * (double)bsize;
1331 dsize = (uint64_t)((total_space+63*512) / (64*512));
1332 dfree = (uint64_t)((free_space+63*512) / (64*512));
1334 if (dsize > 0xFFFF) dsize = 0xFFFF;
1335 if (dfree > 0xFFFF) dfree = 0xFFFF;
1337 SSVAL(req->outbuf,smb_vwv0,dsize);
1338 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1339 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1340 SSVAL(req->outbuf,smb_vwv3,dfree);
1342 SSVAL(req->outbuf,smb_vwv0,dsize);
1343 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1344 SSVAL(req->outbuf,smb_vwv2,512);
1345 SSVAL(req->outbuf,smb_vwv3,dfree);
1348 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1350 END_PROFILE(SMBdskattr);
1355 * Utility function to split the filename from the directory.
1357 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1358 char **fname_dir_out,
1359 char **fname_mask_out)
1361 const char *p = NULL;
1362 char *fname_dir = NULL;
1363 char *fname_mask = NULL;
1365 p = strrchr_m(fname_in, '/');
1367 fname_dir = talloc_strdup(ctx, ".");
1368 fname_mask = talloc_strdup(ctx, fname_in);
1370 fname_dir = talloc_strndup(ctx, fname_in,
1371 PTR_DIFF(p, fname_in));
1372 fname_mask = talloc_strdup(ctx, p+1);
1375 if (!fname_dir || !fname_mask) {
1376 TALLOC_FREE(fname_dir);
1377 TALLOC_FREE(fname_mask);
1378 return NT_STATUS_NO_MEMORY;
1381 *fname_dir_out = fname_dir;
1382 *fname_mask_out = fname_mask;
1383 return NT_STATUS_OK;
1386 /****************************************************************************
1388 Can be called from SMBsearch, SMBffirst or SMBfunique.
1389 ****************************************************************************/
1391 void reply_search(struct smb_request *req)
1393 connection_struct *conn = req->conn;
1395 const char *mask = NULL;
1396 char *directory = NULL;
1397 struct smb_filename *smb_fname = NULL;
1401 struct timespec date;
1403 unsigned int numentries = 0;
1404 unsigned int maxentries = 0;
1405 bool finished = False;
1410 bool check_descend = False;
1411 bool expect_close = False;
1413 bool mask_contains_wcard = False;
1414 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1415 TALLOC_CTX *ctx = talloc_tos();
1416 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1417 struct dptr_struct *dirptr = NULL;
1418 struct smbd_server_connection *sconn = req->sconn;
1420 START_PROFILE(SMBsearch);
1423 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1427 if (lp_posix_pathnames()) {
1428 reply_unknown_new(req, req->cmd);
1432 /* If we were called as SMBffirst then we must expect close. */
1433 if(req->cmd == SMBffirst) {
1434 expect_close = True;
1437 reply_outbuf(req, 1, 3);
1438 maxentries = SVAL(req->vwv+0, 0);
1439 dirtype = SVAL(req->vwv+1, 0);
1440 p = (const char *)req->buf + 1;
1441 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1442 &nt_status, &mask_contains_wcard);
1443 if (!NT_STATUS_IS_OK(nt_status)) {
1444 reply_nterror(req, nt_status);
1449 status_len = SVAL(p, 0);
1452 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1454 if (status_len == 0) {
1455 nt_status = filename_convert(ctx, conn,
1456 req->flags2 & FLAGS2_DFS_PATHNAMES,
1458 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1459 &mask_contains_wcard,
1461 if (!NT_STATUS_IS_OK(nt_status)) {
1462 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1463 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1464 ERRSRV, ERRbadpath);
1467 reply_nterror(req, nt_status);
1471 directory = smb_fname->base_name;
1473 p = strrchr_m(directory,'/');
1474 if ((p != NULL) && (*directory != '/')) {
1476 directory = talloc_strndup(ctx, directory,
1477 PTR_DIFF(p, directory));
1480 directory = talloc_strdup(ctx,".");
1484 reply_nterror(req, NT_STATUS_NO_MEMORY);
1488 memset((char *)status,'\0',21);
1489 SCVAL(status,0,(dirtype & 0x1F));
1491 nt_status = dptr_create(conn,
1498 mask_contains_wcard,
1501 if (!NT_STATUS_IS_OK(nt_status)) {
1502 reply_nterror(req, nt_status);
1505 dptr_num = dptr_dnum(dirptr);
1508 const char *dirpath;
1510 memcpy(status,p,21);
1511 status_dirtype = CVAL(status,0) & 0x1F;
1512 if (status_dirtype != (dirtype & 0x1F)) {
1513 dirtype = status_dirtype;
1516 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1520 dirpath = dptr_path(sconn, dptr_num);
1521 directory = talloc_strdup(ctx, dirpath);
1523 reply_nterror(req, NT_STATUS_NO_MEMORY);
1527 mask = dptr_wcard(sconn, dptr_num);
1532 * For a 'continue' search we have no string. So
1533 * check from the initial saved string.
1535 mask_contains_wcard = ms_has_wild(mask);
1536 dirtype = dptr_attr(sconn, dptr_num);
1539 DEBUG(4,("dptr_num is %d\n",dptr_num));
1541 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1542 dptr_init_search_op(dirptr);
1544 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1545 char buf[DIR_STRUCT_SIZE];
1546 memcpy(buf,status,21);
1547 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1548 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1549 reply_nterror(req, NT_STATUS_NO_MEMORY);
1552 dptr_fill(sconn, buf+12,dptr_num);
1553 if (dptr_zero(buf+12) && (status_len==0)) {
1558 if (message_push_blob(&req->outbuf,
1559 data_blob_const(buf, sizeof(buf)))
1561 reply_nterror(req, NT_STATUS_NO_MEMORY);
1569 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1572 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1573 directory,lp_dontdescend(SNUM(conn))));
1574 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1575 check_descend = True;
1578 for (i=numentries;(i<maxentries) && !finished;i++) {
1579 finished = !get_dir_entry(ctx,
1590 char buf[DIR_STRUCT_SIZE];
1591 memcpy(buf,status,21);
1592 if (!make_dir_struct(ctx,
1598 convert_timespec_to_time_t(date),
1599 !allow_long_path_components)) {
1600 reply_nterror(req, NT_STATUS_NO_MEMORY);
1603 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1606 if (message_push_blob(&req->outbuf,
1607 data_blob_const(buf, sizeof(buf)))
1609 reply_nterror(req, NT_STATUS_NO_MEMORY);
1619 /* If we were called as SMBffirst with smb_search_id == NULL
1620 and no entries were found then return error and close dirptr
1623 if (numentries == 0) {
1624 dptr_close(sconn, &dptr_num);
1625 } else if(expect_close && status_len == 0) {
1626 /* Close the dptr - we know it's gone */
1627 dptr_close(sconn, &dptr_num);
1630 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1631 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1632 dptr_close(sconn, &dptr_num);
1635 if ((numentries == 0) && !mask_contains_wcard) {
1636 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1640 SSVAL(req->outbuf,smb_vwv0,numentries);
1641 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1642 SCVAL(smb_buf(req->outbuf),0,5);
1643 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1645 /* The replies here are never long name. */
1646 SSVAL(req->outbuf, smb_flg2,
1647 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1648 if (!allow_long_path_components) {
1649 SSVAL(req->outbuf, smb_flg2,
1650 SVAL(req->outbuf, smb_flg2)
1651 & (~FLAGS2_LONG_PATH_COMPONENTS));
1654 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1655 SSVAL(req->outbuf, smb_flg2,
1656 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1658 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1659 smb_fn_name(req->cmd),
1666 TALLOC_FREE(directory);
1667 TALLOC_FREE(smb_fname);
1668 END_PROFILE(SMBsearch);
1672 /****************************************************************************
1673 Reply to a fclose (stop directory search).
1674 ****************************************************************************/
1676 void reply_fclose(struct smb_request *req)
1684 bool path_contains_wcard = False;
1685 TALLOC_CTX *ctx = talloc_tos();
1686 struct smbd_server_connection *sconn = req->sconn;
1688 START_PROFILE(SMBfclose);
1690 if (lp_posix_pathnames()) {
1691 reply_unknown_new(req, req->cmd);
1692 END_PROFILE(SMBfclose);
1696 p = (const char *)req->buf + 1;
1697 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1698 &err, &path_contains_wcard);
1699 if (!NT_STATUS_IS_OK(err)) {
1700 reply_nterror(req, err);
1701 END_PROFILE(SMBfclose);
1705 status_len = SVAL(p,0);
1708 if (status_len == 0) {
1709 reply_force_doserror(req, ERRSRV, ERRsrverror);
1710 END_PROFILE(SMBfclose);
1714 memcpy(status,p,21);
1716 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1717 /* Close the dptr - we know it's gone */
1718 dptr_close(sconn, &dptr_num);
1721 reply_outbuf(req, 1, 0);
1722 SSVAL(req->outbuf,smb_vwv0,0);
1724 DEBUG(3,("search close\n"));
1726 END_PROFILE(SMBfclose);
1730 /****************************************************************************
1732 ****************************************************************************/
1734 void reply_open(struct smb_request *req)
1736 connection_struct *conn = req->conn;
1737 struct smb_filename *smb_fname = NULL;
1749 uint32 create_disposition;
1750 uint32 create_options = 0;
1751 uint32_t private_flags = 0;
1753 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1754 TALLOC_CTX *ctx = talloc_tos();
1756 START_PROFILE(SMBopen);
1759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1763 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1764 deny_mode = SVAL(req->vwv+0, 0);
1765 dos_attr = SVAL(req->vwv+1, 0);
1767 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1768 STR_TERMINATE, &status);
1769 if (!NT_STATUS_IS_OK(status)) {
1770 reply_nterror(req, status);
1774 status = filename_convert(ctx,
1776 req->flags2 & FLAGS2_DFS_PATHNAMES,
1781 if (!NT_STATUS_IS_OK(status)) {
1782 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1783 reply_botherror(req,
1784 NT_STATUS_PATH_NOT_COVERED,
1785 ERRSRV, ERRbadpath);
1788 reply_nterror(req, status);
1792 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1793 OPENX_FILE_EXISTS_OPEN, &access_mask,
1794 &share_mode, &create_disposition,
1795 &create_options, &private_flags)) {
1796 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1800 status = SMB_VFS_CREATE_FILE(
1803 0, /* root_dir_fid */
1804 smb_fname, /* fname */
1805 access_mask, /* access_mask */
1806 share_mode, /* share_access */
1807 create_disposition, /* create_disposition*/
1808 create_options, /* create_options */
1809 dos_attr, /* file_attributes */
1810 oplock_request, /* oplock_request */
1811 0, /* allocation_size */
1818 if (!NT_STATUS_IS_OK(status)) {
1819 if (open_was_deferred(req->mid)) {
1820 /* We have re-scheduled this call. */
1823 reply_openerror(req, status);
1827 size = smb_fname->st.st_ex_size;
1828 fattr = dos_mode(conn, smb_fname);
1830 /* Deal with other possible opens having a modified
1832 if (ask_sharemode) {
1833 struct timespec write_time_ts;
1835 ZERO_STRUCT(write_time_ts);
1836 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1837 if (!null_timespec(write_time_ts)) {
1838 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1842 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1844 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1845 DEBUG(3,("attempt to open a directory %s\n",
1847 close_file(req, fsp, ERROR_CLOSE);
1848 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1849 ERRDOS, ERRnoaccess);
1853 reply_outbuf(req, 7, 0);
1854 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1855 SSVAL(req->outbuf,smb_vwv1,fattr);
1856 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1857 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1859 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1861 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1862 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1864 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1865 SCVAL(req->outbuf,smb_flg,
1866 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1869 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1870 SCVAL(req->outbuf,smb_flg,
1871 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1874 TALLOC_FREE(smb_fname);
1875 END_PROFILE(SMBopen);
1879 /****************************************************************************
1880 Reply to an open and X.
1881 ****************************************************************************/
1883 void reply_open_and_X(struct smb_request *req)
1885 connection_struct *conn = req->conn;
1886 struct smb_filename *smb_fname = NULL;
1891 /* Breakout the oplock request bits so we can set the
1892 reply bits separately. */
1893 int ex_oplock_request;
1894 int core_oplock_request;
1897 int smb_sattr = SVAL(req->vwv+4, 0);
1898 uint32 smb_time = make_unix_date3(req->vwv+6);
1906 uint64_t allocation_size;
1907 ssize_t retval = -1;
1910 uint32 create_disposition;
1911 uint32 create_options = 0;
1912 uint32_t private_flags = 0;
1913 TALLOC_CTX *ctx = talloc_tos();
1915 START_PROFILE(SMBopenX);
1917 if (req->wct < 15) {
1918 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1922 open_flags = SVAL(req->vwv+2, 0);
1923 deny_mode = SVAL(req->vwv+3, 0);
1924 smb_attr = SVAL(req->vwv+5, 0);
1925 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1926 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1927 oplock_request = ex_oplock_request | core_oplock_request;
1928 smb_ofun = SVAL(req->vwv+8, 0);
1929 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1931 /* If it's an IPC, pass off the pipe handler. */
1933 if (lp_nt_pipe_support()) {
1934 reply_open_pipe_and_X(conn, req);
1936 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1941 /* XXXX we need to handle passed times, sattr and flags */
1942 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1943 STR_TERMINATE, &status);
1944 if (!NT_STATUS_IS_OK(status)) {
1945 reply_nterror(req, status);
1949 status = filename_convert(ctx,
1951 req->flags2 & FLAGS2_DFS_PATHNAMES,
1956 if (!NT_STATUS_IS_OK(status)) {
1957 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1958 reply_botherror(req,
1959 NT_STATUS_PATH_NOT_COVERED,
1960 ERRSRV, ERRbadpath);
1963 reply_nterror(req, status);
1967 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1969 &access_mask, &share_mode,
1970 &create_disposition,
1973 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1977 status = SMB_VFS_CREATE_FILE(
1980 0, /* root_dir_fid */
1981 smb_fname, /* fname */
1982 access_mask, /* access_mask */
1983 share_mode, /* share_access */
1984 create_disposition, /* create_disposition*/
1985 create_options, /* create_options */
1986 smb_attr, /* file_attributes */
1987 oplock_request, /* oplock_request */
1988 0, /* allocation_size */
1993 &smb_action); /* pinfo */
1995 if (!NT_STATUS_IS_OK(status)) {
1996 if (open_was_deferred(req->mid)) {
1997 /* We have re-scheduled this call. */
2000 reply_openerror(req, status);
2004 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2005 if the file is truncated or created. */
2006 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2007 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2008 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2009 close_file(req, fsp, ERROR_CLOSE);
2010 reply_nterror(req, NT_STATUS_DISK_FULL);
2013 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
2015 close_file(req, fsp, ERROR_CLOSE);
2016 reply_nterror(req, NT_STATUS_DISK_FULL);
2019 status = vfs_stat_fsp(fsp);
2020 if (!NT_STATUS_IS_OK(status)) {
2021 close_file(req, fsp, ERROR_CLOSE);
2022 reply_nterror(req, status);
2027 fattr = dos_mode(conn, fsp->fsp_name);
2028 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2029 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2030 close_file(req, fsp, ERROR_CLOSE);
2031 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2035 /* If the caller set the extended oplock request bit
2036 and we granted one (by whatever means) - set the
2037 correct bit for extended oplock reply.
2040 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2041 smb_action |= EXTENDED_OPLOCK_GRANTED;
2044 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2045 smb_action |= EXTENDED_OPLOCK_GRANTED;
2048 /* If the caller set the core oplock request bit
2049 and we granted one (by whatever means) - set the
2050 correct bit for core oplock reply.
2053 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2054 reply_outbuf(req, 19, 0);
2056 reply_outbuf(req, 15, 0);
2059 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2060 SCVAL(req->outbuf, smb_flg,
2061 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2064 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2065 SCVAL(req->outbuf, smb_flg,
2066 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2069 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2070 SSVAL(req->outbuf,smb_vwv3,fattr);
2071 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2072 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2074 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2076 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2077 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2078 SSVAL(req->outbuf,smb_vwv11,smb_action);
2080 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2081 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2086 TALLOC_FREE(smb_fname);
2087 END_PROFILE(SMBopenX);
2091 /****************************************************************************
2092 Reply to a SMBulogoffX.
2093 ****************************************************************************/
2095 void reply_ulogoffX(struct smb_request *req)
2097 struct smbd_server_connection *sconn = req->sconn;
2100 START_PROFILE(SMBulogoffX);
2102 vuser = get_valid_user_struct(sconn, req->vuid);
2105 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2109 /* in user level security we are supposed to close any files
2110 open by this user */
2111 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2112 file_close_user(sconn, req->vuid);
2115 invalidate_vuid(sconn, req->vuid);
2117 reply_outbuf(req, 2, 0);
2119 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2121 END_PROFILE(SMBulogoffX);
2122 req->vuid = UID_FIELD_INVALID;
2126 /****************************************************************************
2127 Reply to a mknew or a create.
2128 ****************************************************************************/
2130 void reply_mknew(struct smb_request *req)
2132 connection_struct *conn = req->conn;
2133 struct smb_filename *smb_fname = NULL;
2136 struct smb_file_time ft;
2138 int oplock_request = 0;
2140 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2141 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2142 uint32 create_disposition;
2143 uint32 create_options = 0;
2144 TALLOC_CTX *ctx = talloc_tos();
2146 START_PROFILE(SMBcreate);
2150 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2154 fattr = SVAL(req->vwv+0, 0);
2155 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2158 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2160 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2161 STR_TERMINATE, &status);
2162 if (!NT_STATUS_IS_OK(status)) {
2163 reply_nterror(req, status);
2167 status = filename_convert(ctx,
2169 req->flags2 & FLAGS2_DFS_PATHNAMES,
2174 if (!NT_STATUS_IS_OK(status)) {
2175 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2176 reply_botherror(req,
2177 NT_STATUS_PATH_NOT_COVERED,
2178 ERRSRV, ERRbadpath);
2181 reply_nterror(req, status);
2185 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2186 DEBUG(0,("Attempt to create file (%s) with volid set - "
2187 "please report this\n",
2188 smb_fname_str_dbg(smb_fname)));
2191 if(req->cmd == SMBmknew) {
2192 /* We should fail if file exists. */
2193 create_disposition = FILE_CREATE;
2195 /* Create if file doesn't exist, truncate if it does. */
2196 create_disposition = FILE_OVERWRITE_IF;
2199 status = SMB_VFS_CREATE_FILE(
2202 0, /* root_dir_fid */
2203 smb_fname, /* fname */
2204 access_mask, /* access_mask */
2205 share_mode, /* share_access */
2206 create_disposition, /* create_disposition*/
2207 create_options, /* create_options */
2208 fattr, /* file_attributes */
2209 oplock_request, /* oplock_request */
2210 0, /* allocation_size */
2211 0, /* private_flags */
2217 if (!NT_STATUS_IS_OK(status)) {
2218 if (open_was_deferred(req->mid)) {
2219 /* We have re-scheduled this call. */
2222 reply_openerror(req, status);
2226 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2227 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2228 if (!NT_STATUS_IS_OK(status)) {
2229 END_PROFILE(SMBcreate);
2233 reply_outbuf(req, 1, 0);
2234 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2236 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2237 SCVAL(req->outbuf,smb_flg,
2238 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2241 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2242 SCVAL(req->outbuf,smb_flg,
2243 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2246 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2247 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2248 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2249 (unsigned int)fattr));
2252 TALLOC_FREE(smb_fname);
2253 END_PROFILE(SMBcreate);
2257 /****************************************************************************
2258 Reply to a create temporary file.
2259 ****************************************************************************/
2261 void reply_ctemp(struct smb_request *req)
2263 connection_struct *conn = req->conn;
2264 struct smb_filename *smb_fname = NULL;
2272 TALLOC_CTX *ctx = talloc_tos();
2274 START_PROFILE(SMBctemp);
2277 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2281 fattr = SVAL(req->vwv+0, 0);
2282 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2284 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2285 STR_TERMINATE, &status);
2286 if (!NT_STATUS_IS_OK(status)) {
2287 reply_nterror(req, status);
2291 fname = talloc_asprintf(ctx,
2295 fname = talloc_strdup(ctx, "TMXXXXXX");
2299 reply_nterror(req, NT_STATUS_NO_MEMORY);
2303 status = filename_convert(ctx, conn,
2304 req->flags2 & FLAGS2_DFS_PATHNAMES,
2309 if (!NT_STATUS_IS_OK(status)) {
2310 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2311 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2312 ERRSRV, ERRbadpath);
2315 reply_nterror(req, status);
2319 tmpfd = mkstemp(smb_fname->base_name);
2321 reply_nterror(req, map_nt_error_from_unix(errno));
2325 SMB_VFS_STAT(conn, smb_fname);
2327 /* We should fail if file does not exist. */
2328 status = SMB_VFS_CREATE_FILE(
2331 0, /* root_dir_fid */
2332 smb_fname, /* fname */
2333 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2334 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2335 FILE_OPEN, /* create_disposition*/
2336 0, /* create_options */
2337 fattr, /* file_attributes */
2338 oplock_request, /* oplock_request */
2339 0, /* allocation_size */
2340 0, /* private_flags */
2346 /* close fd from mkstemp() */
2349 if (!NT_STATUS_IS_OK(status)) {
2350 if (open_was_deferred(req->mid)) {
2351 /* We have re-scheduled this call. */
2354 reply_openerror(req, status);
2358 reply_outbuf(req, 1, 0);
2359 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2361 /* the returned filename is relative to the directory */
2362 s = strrchr_m(fsp->fsp_name->base_name, '/');
2364 s = fsp->fsp_name->base_name;
2370 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2371 thing in the byte section. JRA */
2372 SSVALS(p, 0, -1); /* what is this? not in spec */
2374 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2376 reply_nterror(req, NT_STATUS_NO_MEMORY);
2380 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2381 SCVAL(req->outbuf, smb_flg,
2382 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2385 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2386 SCVAL(req->outbuf, smb_flg,
2387 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2390 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2391 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2392 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2394 TALLOC_FREE(smb_fname);
2395 END_PROFILE(SMBctemp);
2399 /*******************************************************************
2400 Check if a user is allowed to rename a file.
2401 ********************************************************************/
2403 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2406 if (!CAN_WRITE(conn)) {
2407 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2410 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2411 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2412 /* Only bother to read the DOS attribute if we might deny the
2413 rename on the grounds of attribute missmatch. */
2414 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2415 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2416 return NT_STATUS_NO_SUCH_FILE;
2420 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2421 if (fsp->posix_open) {
2422 return NT_STATUS_OK;
2425 /* If no pathnames are open below this
2426 directory, allow the rename. */
2428 if (file_find_subpath(fsp)) {
2429 return NT_STATUS_ACCESS_DENIED;
2431 return NT_STATUS_OK;
2434 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2435 return NT_STATUS_OK;
2438 return NT_STATUS_ACCESS_DENIED;
2441 /*******************************************************************
2442 * unlink a file with all relevant access checks
2443 *******************************************************************/
2445 static NTSTATUS do_unlink(connection_struct *conn,
2446 struct smb_request *req,
2447 struct smb_filename *smb_fname,
2452 uint32 dirtype_orig = dirtype;
2455 bool posix_paths = lp_posix_pathnames();
2457 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2458 smb_fname_str_dbg(smb_fname),
2461 if (!CAN_WRITE(conn)) {
2462 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2466 ret = SMB_VFS_LSTAT(conn, smb_fname);
2468 ret = SMB_VFS_STAT(conn, smb_fname);
2471 return map_nt_error_from_unix(errno);
2474 fattr = dos_mode(conn, smb_fname);
2476 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2477 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2480 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2482 return NT_STATUS_NO_SUCH_FILE;
2485 if (!dir_check_ftype(conn, fattr, dirtype)) {
2486 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2487 return NT_STATUS_FILE_IS_A_DIRECTORY;
2489 return NT_STATUS_NO_SUCH_FILE;
2492 if (dirtype_orig & 0x8000) {
2493 /* These will never be set for POSIX. */
2494 return NT_STATUS_NO_SUCH_FILE;
2498 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2499 return NT_STATUS_FILE_IS_A_DIRECTORY;
2502 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2503 return NT_STATUS_NO_SUCH_FILE;
2506 if (dirtype & 0xFF00) {
2507 /* These will never be set for POSIX. */
2508 return NT_STATUS_NO_SUCH_FILE;
2513 return NT_STATUS_NO_SUCH_FILE;
2516 /* Can't delete a directory. */
2517 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2518 return NT_STATUS_FILE_IS_A_DIRECTORY;
2523 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2524 return NT_STATUS_OBJECT_NAME_INVALID;
2525 #endif /* JRATEST */
2527 /* On open checks the open itself will check the share mode, so
2528 don't do it here as we'll get it wrong. */
2530 status = SMB_VFS_CREATE_FILE
2533 0, /* root_dir_fid */
2534 smb_fname, /* fname */
2535 DELETE_ACCESS, /* access_mask */
2536 FILE_SHARE_NONE, /* share_access */
2537 FILE_OPEN, /* create_disposition*/
2538 FILE_NON_DIRECTORY_FILE, /* create_options */
2539 /* file_attributes */
2540 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2541 FILE_ATTRIBUTE_NORMAL,
2542 0, /* oplock_request */
2543 0, /* allocation_size */
2544 0, /* private_flags */
2550 if (!NT_STATUS_IS_OK(status)) {
2551 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2552 nt_errstr(status)));
2556 status = can_set_delete_on_close(fsp, fattr);
2557 if (!NT_STATUS_IS_OK(status)) {
2558 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2560 smb_fname_str_dbg(smb_fname),
2561 nt_errstr(status)));
2562 close_file(req, fsp, NORMAL_CLOSE);
2566 /* The set is across all open files on this dev/inode pair. */
2567 if (!set_delete_on_close(fsp, True, conn->session_info->unix_token)) {
2568 close_file(req, fsp, NORMAL_CLOSE);
2569 return NT_STATUS_ACCESS_DENIED;
2572 return close_file(req, fsp, NORMAL_CLOSE);
2575 /****************************************************************************
2576 The guts of the unlink command, split out so it may be called by the NT SMB
2578 ****************************************************************************/
2580 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2581 uint32 dirtype, struct smb_filename *smb_fname,
2584 char *fname_dir = NULL;
2585 char *fname_mask = NULL;
2587 NTSTATUS status = NT_STATUS_OK;
2588 TALLOC_CTX *ctx = talloc_tos();
2590 /* Split up the directory from the filename/mask. */
2591 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2592 &fname_dir, &fname_mask);
2593 if (!NT_STATUS_IS_OK(status)) {
2598 * We should only check the mangled cache
2599 * here if unix_convert failed. This means
2600 * that the path in 'mask' doesn't exist
2601 * on the file system and so we need to look
2602 * for a possible mangle. This patch from
2603 * Tine Smukavec <valentin.smukavec@hermes.si>.
2606 if (!VALID_STAT(smb_fname->st) &&
2607 mangle_is_mangled(fname_mask, conn->params)) {
2608 char *new_mask = NULL;
2609 mangle_lookup_name_from_8_3(ctx, fname_mask,
2610 &new_mask, conn->params);
2612 TALLOC_FREE(fname_mask);
2613 fname_mask = new_mask;
2620 * Only one file needs to be unlinked. Append the mask back
2621 * onto the directory.
2623 TALLOC_FREE(smb_fname->base_name);
2624 if (ISDOT(fname_dir)) {
2625 /* Ensure we use canonical names on open. */
2626 smb_fname->base_name = talloc_asprintf(smb_fname,
2630 smb_fname->base_name = talloc_asprintf(smb_fname,
2635 if (!smb_fname->base_name) {
2636 status = NT_STATUS_NO_MEMORY;
2640 dirtype = FILE_ATTRIBUTE_NORMAL;
2643 status = check_name(conn, smb_fname->base_name);
2644 if (!NT_STATUS_IS_OK(status)) {
2648 status = do_unlink(conn, req, smb_fname, dirtype);
2649 if (!NT_STATUS_IS_OK(status)) {
2655 struct smb_Dir *dir_hnd = NULL;
2657 const char *dname = NULL;
2658 char *talloced = NULL;
2660 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2661 status = NT_STATUS_OBJECT_NAME_INVALID;
2665 if (strequal(fname_mask,"????????.???")) {
2666 TALLOC_FREE(fname_mask);
2667 fname_mask = talloc_strdup(ctx, "*");
2669 status = NT_STATUS_NO_MEMORY;
2674 status = check_name(conn, fname_dir);
2675 if (!NT_STATUS_IS_OK(status)) {
2679 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2681 if (dir_hnd == NULL) {
2682 status = map_nt_error_from_unix(errno);
2686 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2687 the pattern matches against the long name, otherwise the short name
2688 We don't implement this yet XXXX
2691 status = NT_STATUS_NO_SUCH_FILE;
2693 while ((dname = ReadDirName(dir_hnd, &offset,
2694 &smb_fname->st, &talloced))) {
2695 TALLOC_CTX *frame = talloc_stackframe();
2697 if (!is_visible_file(conn, fname_dir, dname,
2698 &smb_fname->st, true)) {
2700 TALLOC_FREE(talloced);
2704 /* Quick check for "." and ".." */
2705 if (ISDOT(dname) || ISDOTDOT(dname)) {
2707 TALLOC_FREE(talloced);
2711 if(!mask_match(dname, fname_mask,
2712 conn->case_sensitive)) {
2714 TALLOC_FREE(talloced);
2718 TALLOC_FREE(smb_fname->base_name);
2719 if (ISDOT(fname_dir)) {
2720 /* Ensure we use canonical names on open. */
2721 smb_fname->base_name =
2722 talloc_asprintf(smb_fname, "%s",
2725 smb_fname->base_name =
2726 talloc_asprintf(smb_fname, "%s/%s",
2730 if (!smb_fname->base_name) {
2731 TALLOC_FREE(dir_hnd);
2732 status = NT_STATUS_NO_MEMORY;
2734 TALLOC_FREE(talloced);
2738 status = check_name(conn, smb_fname->base_name);
2739 if (!NT_STATUS_IS_OK(status)) {
2740 TALLOC_FREE(dir_hnd);
2742 TALLOC_FREE(talloced);
2746 status = do_unlink(conn, req, smb_fname, dirtype);
2747 if (!NT_STATUS_IS_OK(status)) {
2749 TALLOC_FREE(talloced);
2754 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2755 smb_fname->base_name));
2758 TALLOC_FREE(talloced);
2760 TALLOC_FREE(dir_hnd);
2763 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2764 status = map_nt_error_from_unix(errno);
2768 TALLOC_FREE(fname_dir);
2769 TALLOC_FREE(fname_mask);
2773 /****************************************************************************
2775 ****************************************************************************/
2777 void reply_unlink(struct smb_request *req)
2779 connection_struct *conn = req->conn;
2781 struct smb_filename *smb_fname = NULL;
2784 bool path_contains_wcard = False;
2785 TALLOC_CTX *ctx = talloc_tos();
2787 START_PROFILE(SMBunlink);
2790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2794 dirtype = SVAL(req->vwv+0, 0);
2796 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2797 STR_TERMINATE, &status,
2798 &path_contains_wcard);
2799 if (!NT_STATUS_IS_OK(status)) {
2800 reply_nterror(req, status);
2804 status = filename_convert(ctx, conn,
2805 req->flags2 & FLAGS2_DFS_PATHNAMES,
2807 UCF_COND_ALLOW_WCARD_LCOMP,
2808 &path_contains_wcard,
2810 if (!NT_STATUS_IS_OK(status)) {
2811 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2812 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2813 ERRSRV, ERRbadpath);
2816 reply_nterror(req, status);
2820 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2822 status = unlink_internals(conn, req, dirtype, smb_fname,
2823 path_contains_wcard);
2824 if (!NT_STATUS_IS_OK(status)) {
2825 if (open_was_deferred(req->mid)) {
2826 /* We have re-scheduled this call. */
2829 reply_nterror(req, status);
2833 reply_outbuf(req, 0, 0);
2835 TALLOC_FREE(smb_fname);
2836 END_PROFILE(SMBunlink);
2840 /****************************************************************************
2842 ****************************************************************************/
2844 static void fail_readraw(void)
2846 const char *errstr = talloc_asprintf(talloc_tos(),
2847 "FAIL ! reply_readbraw: socket write fail (%s)",
2852 exit_server_cleanly(errstr);
2855 /****************************************************************************
2856 Fake (read/write) sendfile. Returns -1 on read or write fail.
2857 ****************************************************************************/
2859 ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread)
2862 size_t tosend = nread;
2869 bufsize = MIN(nread, 65536);
2871 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2875 while (tosend > 0) {
2879 if (tosend > bufsize) {
2884 ret = read_file(fsp,buf,startpos,cur_read);
2890 /* If we had a short read, fill with zeros. */
2891 if (ret < cur_read) {
2892 memset(buf + ret, '\0', cur_read - ret);
2895 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2897 char addr[INET6_ADDRSTRLEN];
2899 * Try and give an error message saying what
2902 DEBUG(0, ("write_data failed for client %s. "
2904 get_peer_addr(fsp->conn->sconn->sock, addr,
2911 startpos += cur_read;
2915 return (ssize_t)nread;
2918 /****************************************************************************
2919 Deal with the case of sendfile reading less bytes from the file than
2920 requested. Fill with zeros (all we can do).
2921 ****************************************************************************/
2923 void sendfile_short_send(files_struct *fsp,
2928 #define SHORT_SEND_BUFSIZE 1024
2929 if (nread < headersize) {
2930 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2931 "header for file %s (%s). Terminating\n",
2932 fsp_str_dbg(fsp), strerror(errno)));
2933 exit_server_cleanly("sendfile_short_send failed");
2936 nread -= headersize;
2938 if (nread < smb_maxcnt) {
2939 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2941 exit_server_cleanly("sendfile_short_send: "
2945 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2946 "with zeros !\n", fsp_str_dbg(fsp)));
2948 while (nread < smb_maxcnt) {
2950 * We asked for the real file size and told sendfile
2951 * to not go beyond the end of the file. But it can
2952 * happen that in between our fstat call and the
2953 * sendfile call the file was truncated. This is very
2954 * bad because we have already announced the larger
2955 * number of bytes to the client.
2957 * The best we can do now is to send 0-bytes, just as
2958 * a read from a hole in a sparse file would do.
2960 * This should happen rarely enough that I don't care
2961 * about efficiency here :-)
2965 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2966 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2968 char addr[INET6_ADDRSTRLEN];
2970 * Try and give an error message saying what
2973 DEBUG(0, ("write_data failed for client %s. "
2976 fsp->conn->sconn->sock, addr,
2979 exit_server_cleanly("sendfile_short_send: "
2980 "write_data failed");
2988 /****************************************************************************
2989 Return a readbraw error (4 bytes of zero).
2990 ****************************************************************************/
2992 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2998 smbd_lock_socket(sconn);
2999 if (write_data(sconn->sock,header,4) != 4) {
3000 char addr[INET6_ADDRSTRLEN];
3002 * Try and give an error message saying what
3005 DEBUG(0, ("write_data failed for client %s. "
3007 get_peer_addr(sconn->sock, addr, sizeof(addr)),
3012 smbd_unlock_socket(sconn);
3015 /****************************************************************************
3016 Use sendfile in readbraw.
3017 ****************************************************************************/
3019 static void send_file_readbraw(connection_struct *conn,
3020 struct smb_request *req,
3026 struct smbd_server_connection *sconn = req->sconn;
3027 char *outbuf = NULL;
3031 * We can only use sendfile on a non-chained packet
3032 * but we can use on a non-oplocked file. tridge proved this
3033 * on a train in Germany :-). JRA.
3034 * reply_readbraw has already checked the length.
3037 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3038 (fsp->wcp == NULL) &&
3039 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3040 ssize_t sendfile_read = -1;
3042 DATA_BLOB header_blob;
3044 _smb_setlen(header,nread);
3045 header_blob = data_blob_const(header, 4);
3047 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3048 &header_blob, startpos,
3050 if (sendfile_read == -1) {
3051 /* Returning ENOSYS means no data at all was sent.
3052 * Do this as a normal read. */
3053 if (errno == ENOSYS) {
3054 goto normal_readbraw;
3058 * Special hack for broken Linux with no working sendfile. If we
3059 * return EINTR we sent the header but not the rest of the data.
3060 * Fake this up by doing read/write calls.
3062 if (errno == EINTR) {
3063 /* Ensure we don't do this again. */
3064 set_use_sendfile(SNUM(conn), False);
3065 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3067 if (fake_sendfile(fsp, startpos, nread) == -1) {
3068 DEBUG(0,("send_file_readbraw: "
3069 "fake_sendfile failed for "
3073 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3078 DEBUG(0,("send_file_readbraw: sendfile failed for "
3079 "file %s (%s). Terminating\n",
3080 fsp_str_dbg(fsp), strerror(errno)));
3081 exit_server_cleanly("send_file_readbraw sendfile failed");
3082 } else if (sendfile_read == 0) {
3084 * Some sendfile implementations return 0 to indicate
3085 * that there was a short read, but nothing was
3086 * actually written to the socket. In this case,
3087 * fallback to the normal read path so the header gets
3088 * the correct byte count.
3090 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3091 "bytes falling back to the normal read: "
3092 "%s\n", fsp_str_dbg(fsp)));
3093 goto normal_readbraw;
3096 /* Deal with possible short send. */
3097 if (sendfile_read != 4+nread) {
3098 sendfile_short_send(fsp, sendfile_read, 4, nread);
3105 outbuf = talloc_array(NULL, char, nread+4);
3107 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3108 (unsigned)(nread+4)));
3109 reply_readbraw_error(sconn);
3114 ret = read_file(fsp,outbuf+4,startpos,nread);
3115 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3124 _smb_setlen(outbuf,ret);
3125 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3126 char addr[INET6_ADDRSTRLEN];
3128 * Try and give an error message saying what
3131 DEBUG(0, ("write_data failed for client %s. "
3133 get_peer_addr(fsp->conn->sconn->sock, addr,
3140 TALLOC_FREE(outbuf);
3143 /****************************************************************************
3144 Reply to a readbraw (core+ protocol).
3145 ****************************************************************************/
3147 void reply_readbraw(struct smb_request *req)
3149 connection_struct *conn = req->conn;
3150 struct smbd_server_connection *sconn = req->sconn;
3151 ssize_t maxcount,mincount;
3155 struct lock_struct lock;
3158 START_PROFILE(SMBreadbraw);
3160 if (srv_is_signing_active(sconn) ||
3161 is_encrypted_packet(req->inbuf)) {
3162 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3163 "raw reads/writes are disallowed.");
3167 reply_readbraw_error(sconn);
3168 END_PROFILE(SMBreadbraw);
3172 if (sconn->smb1.echo_handler.trusted_fde) {
3173 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3174 "'async smb echo handler = yes'\n"));
3175 reply_readbraw_error(sconn);
3176 END_PROFILE(SMBreadbraw);
3181 * Special check if an oplock break has been issued
3182 * and the readraw request croses on the wire, we must
3183 * return a zero length response here.
3186 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3189 * We have to do a check_fsp by hand here, as
3190 * we must always return 4 zero bytes on error,
3194 if (!fsp || !conn || conn != fsp->conn ||
3195 req->vuid != fsp->vuid ||
3196 fsp->is_directory || fsp->fh->fd == -1) {
3198 * fsp could be NULL here so use the value from the packet. JRA.
3200 DEBUG(3,("reply_readbraw: fnum %d not valid "
3202 (int)SVAL(req->vwv+0, 0)));
3203 reply_readbraw_error(sconn);
3204 END_PROFILE(SMBreadbraw);
3208 /* Do a "by hand" version of CHECK_READ. */
3209 if (!(fsp->can_read ||
3210 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3211 (fsp->access_mask & FILE_EXECUTE)))) {
3212 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3213 (int)SVAL(req->vwv+0, 0)));
3214 reply_readbraw_error(sconn);
3215 END_PROFILE(SMBreadbraw);
3219 flush_write_cache(fsp, READRAW_FLUSH);
3221 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3222 if(req->wct == 10) {
3224 * This is a large offset (64 bit) read.
3226 #ifdef LARGE_SMB_OFF_T
3228 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3230 #else /* !LARGE_SMB_OFF_T */
3233 * Ensure we haven't been sent a >32 bit offset.
3236 if(IVAL(req->vwv+8, 0) != 0) {
3237 DEBUG(0,("reply_readbraw: large offset "
3238 "(%x << 32) used and we don't support "
3239 "64 bit offsets.\n",
3240 (unsigned int)IVAL(req->vwv+8, 0) ));
3241 reply_readbraw_error(sconn);
3242 END_PROFILE(SMBreadbraw);
3246 #endif /* LARGE_SMB_OFF_T */
3249 DEBUG(0,("reply_readbraw: negative 64 bit "
3250 "readraw offset (%.0f) !\n",
3251 (double)startpos ));
3252 reply_readbraw_error(sconn);
3253 END_PROFILE(SMBreadbraw);
3258 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3259 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3261 /* ensure we don't overrun the packet size */
3262 maxcount = MIN(65535,maxcount);
3264 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3265 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3268 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3269 reply_readbraw_error(sconn);
3270 END_PROFILE(SMBreadbraw);
3274 if (fsp_stat(fsp) == 0) {
3275 size = fsp->fsp_name->st.st_ex_size;
3278 if (startpos >= size) {
3281 nread = MIN(maxcount,(size - startpos));
3284 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3285 if (nread < mincount)
3289 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3290 "min=%lu nread=%lu\n",
3291 fsp->fnum, (double)startpos,
3292 (unsigned long)maxcount,
3293 (unsigned long)mincount,
3294 (unsigned long)nread ) );
3296 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3298 DEBUG(5,("reply_readbraw finished\n"));
3300 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3302 END_PROFILE(SMBreadbraw);
3307 #define DBGC_CLASS DBGC_LOCKING
3309 /****************************************************************************
3310 Reply to a lockread (core+ protocol).
3311 ****************************************************************************/
3313 void reply_lockread(struct smb_request *req)
3315 connection_struct *conn = req->conn;
3322 struct byte_range_lock *br_lck = NULL;
3324 struct smbd_server_connection *sconn = req->sconn;
3326 START_PROFILE(SMBlockread);
3329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3330 END_PROFILE(SMBlockread);
3334 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3336 if (!check_fsp(conn, req, fsp)) {
3337 END_PROFILE(SMBlockread);
3341 if (!CHECK_READ(fsp,req)) {
3342 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3343 END_PROFILE(SMBlockread);
3347 numtoread = SVAL(req->vwv+1, 0);
3348 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3350 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3352 reply_outbuf(req, 5, numtoread + 3);
3354 data = smb_buf(req->outbuf) + 3;
3357 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3358 * protocol request that predates the read/write lock concept.
3359 * Thus instead of asking for a read lock here we need to ask
3360 * for a write lock. JRA.
3361 * Note that the requested lock size is unaffected by max_recv.
3364 br_lck = do_lock(req->sconn->msg_ctx,
3366 (uint64_t)req->smbpid,
3367 (uint64_t)numtoread,
3371 False, /* Non-blocking lock. */
3375 TALLOC_FREE(br_lck);
3377 if (NT_STATUS_V(status)) {
3378 reply_nterror(req, status);
3379 END_PROFILE(SMBlockread);
3384 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3387 if (numtoread > sconn->smb1.negprot.max_recv) {
3388 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3389 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3390 (unsigned int)numtoread,
3391 (unsigned int)sconn->smb1.negprot.max_recv));
3392 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3394 nread = read_file(fsp,data,startpos,numtoread);
3397 reply_nterror(req, map_nt_error_from_unix(errno));
3398 END_PROFILE(SMBlockread);
3402 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3404 SSVAL(req->outbuf,smb_vwv0,nread);
3405 SSVAL(req->outbuf,smb_vwv5,nread+3);
3406 p = smb_buf(req->outbuf);
3407 SCVAL(p,0,0); /* pad byte. */
3410 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3411 fsp->fnum, (int)numtoread, (int)nread));
3413 END_PROFILE(SMBlockread);
3418 #define DBGC_CLASS DBGC_ALL
3420 /****************************************************************************
3422 ****************************************************************************/
3424 void reply_read(struct smb_request *req)
3426 connection_struct *conn = req->conn;
3433 struct lock_struct lock;
3434 struct smbd_server_connection *sconn = req->sconn;
3436 START_PROFILE(SMBread);
3439 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3440 END_PROFILE(SMBread);
3444 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3446 if (!check_fsp(conn, req, fsp)) {
3447 END_PROFILE(SMBread);
3451 if (!CHECK_READ(fsp,req)) {
3452 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3453 END_PROFILE(SMBread);
3457 numtoread = SVAL(req->vwv+1, 0);
3458 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3460 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3463 * The requested read size cannot be greater than max_recv. JRA.
3465 if (numtoread > sconn->smb1.negprot.max_recv) {
3466 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3467 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3468 (unsigned int)numtoread,
3469 (unsigned int)sconn->smb1.negprot.max_recv));
3470 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3473 reply_outbuf(req, 5, numtoread+3);
3475 data = smb_buf(req->outbuf) + 3;
3477 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3478 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3481 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3482 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3483 END_PROFILE(SMBread);
3488 nread = read_file(fsp,data,startpos,numtoread);
3491 reply_nterror(req, map_nt_error_from_unix(errno));
3495 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3497 SSVAL(req->outbuf,smb_vwv0,nread);
3498 SSVAL(req->outbuf,smb_vwv5,nread+3);
3499 SCVAL(smb_buf(req->outbuf),0,1);
3500 SSVAL(smb_buf(req->outbuf),1,nread);
3502 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3503 fsp->fnum, (int)numtoread, (int)nread ) );
3506 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3508 END_PROFILE(SMBread);
3512 /****************************************************************************
3514 ****************************************************************************/
3516 static int setup_readX_header(struct smb_request *req, char *outbuf,
3522 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3523 data = smb_buf(outbuf);
3525 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3527 SCVAL(outbuf,smb_vwv0,0xFF);
3528 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3529 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3530 SSVAL(outbuf,smb_vwv6,
3532 + 1 /* the wct field */
3533 + 12 * sizeof(uint16_t) /* vwv */
3534 + 2); /* the buflen field */
3535 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3536 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3537 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3538 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3542 /****************************************************************************
3543 Reply to a read and X - possibly using sendfile.
3544 ****************************************************************************/
3546 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3547 files_struct *fsp, SMB_OFF_T startpos,
3551 struct lock_struct lock;
3552 int saved_errno = 0;
3554 if(fsp_stat(fsp) == -1) {
3555 reply_nterror(req, map_nt_error_from_unix(errno));
3559 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3560 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3563 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3564 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3568 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3569 (startpos > fsp->fsp_name->st.st_ex_size)
3570 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3572 * We already know that we would do a short read, so don't
3573 * try the sendfile() path.
3575 goto nosendfile_read;
3579 * We can only use sendfile on a non-chained packet
3580 * but we can use on a non-oplocked file. tridge proved this
3581 * on a train in Germany :-). JRA.
3584 if (!req_is_in_chain(req) &&
3585 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3586 (fsp->wcp == NULL) &&
3587 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3588 uint8 headerbuf[smb_size + 12 * 2];
3592 * Set up the packet header before send. We
3593 * assume here the sendfile will work (get the
3594 * correct amount of data).
3597 header = data_blob_const(headerbuf, sizeof(headerbuf));
3599 construct_reply_common_req(req, (char *)headerbuf);
3600 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3602 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3603 startpos, smb_maxcnt);
3605 /* Returning ENOSYS means no data at all was sent.
3606 Do this as a normal read. */
3607 if (errno == ENOSYS) {
3612 * Special hack for broken Linux with no working sendfile. If we
3613 * return EINTR we sent the header but not the rest of the data.
3614 * Fake this up by doing read/write calls.
3617 if (errno == EINTR) {
3618 /* Ensure we don't do this again. */
3619 set_use_sendfile(SNUM(conn), False);
3620 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3621 nread = fake_sendfile(fsp, startpos,
3624 DEBUG(0,("send_file_readX: "
3625 "fake_sendfile failed for "
3629 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3631 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3632 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3633 /* No outbuf here means successful sendfile. */
3637 DEBUG(0,("send_file_readX: sendfile failed for file "
3638 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3640 exit_server_cleanly("send_file_readX sendfile failed");
3641 } else if (nread == 0) {
3643 * Some sendfile implementations return 0 to indicate
3644 * that there was a short read, but nothing was
3645 * actually written to the socket. In this case,
3646 * fallback to the normal read path so the header gets
3647 * the correct byte count.
3649 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3650 "falling back to the normal read: %s\n",
3655 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3656 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3658 /* Deal with possible short send. */
3659 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3660 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3662 /* No outbuf here means successful sendfile. */
3663 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3664 SMB_PERFCOUNT_END(&req->pcd);
3670 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3671 uint8 headerbuf[smb_size + 2*12];
3673 construct_reply_common_req(req, (char *)headerbuf);
3674 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3676 /* Send out the header. */
3677 if (write_data(req->sconn->sock, (char *)headerbuf,
3678 sizeof(headerbuf)) != sizeof(headerbuf)) {
3680 char addr[INET6_ADDRSTRLEN];
3682 * Try and give an error message saying what
3685 DEBUG(0, ("write_data failed for client %s. "
3687 get_peer_addr(req->sconn->sock, addr,
3691 DEBUG(0,("send_file_readX: write_data failed for file "
3692 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3694 exit_server_cleanly("send_file_readX sendfile failed");
3696 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3698 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3699 "file %s (%s).\n", fsp_str_dbg(fsp),
3701 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3708 reply_outbuf(req, 12, smb_maxcnt);
3710 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3711 saved_errno = errno;
3713 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3716 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3720 setup_readX_header(req, (char *)req->outbuf, nread);
3722 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3723 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3729 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3730 TALLOC_FREE(req->outbuf);
3734 /****************************************************************************
3735 Reply to a read and X.
3736 ****************************************************************************/
3738 void reply_read_and_X(struct smb_request *req)
3740 connection_struct *conn = req->conn;
3744 bool big_readX = False;
3746 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3749 START_PROFILE(SMBreadX);
3751 if ((req->wct != 10) && (req->wct != 12)) {
3752 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3756 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3757 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3758 smb_maxcnt = SVAL(req->vwv+5, 0);
3760 /* If it's an IPC, pass off the pipe handler. */
3762 reply_pipe_read_and_X(req);
3763 END_PROFILE(SMBreadX);
3767 if (!check_fsp(conn, req, fsp)) {
3768 END_PROFILE(SMBreadX);
3772 if (!CHECK_READ(fsp,req)) {
3773 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3774 END_PROFILE(SMBreadX);
3778 if (global_client_caps & CAP_LARGE_READX) {
3779 size_t upper_size = SVAL(req->vwv+7, 0);
3780 smb_maxcnt |= (upper_size<<16);
3781 if (upper_size > 1) {
3782 /* Can't do this on a chained packet. */
3783 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3784 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3785 END_PROFILE(SMBreadX);
3788 /* We currently don't do this on signed or sealed data. */
3789 if (srv_is_signing_active(req->sconn) ||
3790 is_encrypted_packet(req->inbuf)) {
3791 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3792 END_PROFILE(SMBreadX);
3795 /* Is there room in the reply for this data ? */
3796 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3798 NT_STATUS_INVALID_PARAMETER);
3799 END_PROFILE(SMBreadX);
3806 if (req->wct == 12) {
3807 #ifdef LARGE_SMB_OFF_T
3809 * This is a large offset (64 bit) read.
3811 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3813 #else /* !LARGE_SMB_OFF_T */
3816 * Ensure we haven't been sent a >32 bit offset.
3819 if(IVAL(req->vwv+10, 0) != 0) {
3820 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3821 "used and we don't support 64 bit offsets.\n",
3822 (unsigned int)IVAL(req->vwv+10, 0) ));
3823 END_PROFILE(SMBreadX);
3824 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3828 #endif /* LARGE_SMB_OFF_T */
3833 NTSTATUS status = schedule_aio_read_and_X(conn,
3838 if (NT_STATUS_IS_OK(status)) {
3839 /* Read scheduled - we're done. */
3842 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3843 /* Real error - report to client. */
3844 END_PROFILE(SMBreadX);
3845 reply_nterror(req, status);
3848 /* NT_STATUS_RETRY - fall back to sync read. */
3851 smbd_lock_socket(req->sconn);
3852 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3853 smbd_unlock_socket(req->sconn);
3856 END_PROFILE(SMBreadX);
3860 /****************************************************************************
3861 Error replies to writebraw must have smb_wct == 1. Fix this up.
3862 ****************************************************************************/
3864 void error_to_writebrawerr(struct smb_request *req)
3866 uint8 *old_outbuf = req->outbuf;
3868 reply_outbuf(req, 1, 0);
3870 memcpy(req->outbuf, old_outbuf, smb_size);
3871 TALLOC_FREE(old_outbuf);
3874 /****************************************************************************
3875 Read 4 bytes of a smb packet and return the smb length of the packet.
3876 Store the result in the buffer. This version of the function will
3877 never return a session keepalive (length of zero).
3878 Timeout is in milliseconds.
3879 ****************************************************************************/
3881 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3884 uint8_t msgtype = NBSSkeepalive;
3886 while (msgtype == NBSSkeepalive) {
3889 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3891 if (!NT_STATUS_IS_OK(status)) {
3892 char addr[INET6_ADDRSTRLEN];
3893 /* Try and give an error message
3894 * saying what client failed. */
3895 DEBUG(0, ("read_fd_with_timeout failed for "
3896 "client %s read error = %s.\n",
3897 get_peer_addr(fd,addr,sizeof(addr)),
3898 nt_errstr(status)));
3902 msgtype = CVAL(inbuf, 0);
3905 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3906 (unsigned long)len));
3908 return NT_STATUS_OK;
3911 /****************************************************************************
3912 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3913 ****************************************************************************/
3915 void reply_writebraw(struct smb_request *req)
3917 connection_struct *conn = req->conn;
3920 ssize_t total_written=0;
3921 size_t numtowrite=0;
3924 const char *data=NULL;
3927 struct lock_struct lock;
3930 START_PROFILE(SMBwritebraw);
3933 * If we ever reply with an error, it must have the SMB command
3934 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3937 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3939 if (srv_is_signing_active(req->sconn)) {
3940 END_PROFILE(SMBwritebraw);
3941 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3942 "raw reads/writes are disallowed.");
3945 if (req->wct < 12) {
3946 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3947 error_to_writebrawerr(req);
3948 END_PROFILE(SMBwritebraw);
3952 if (req->sconn->smb1.echo_handler.trusted_fde) {
3953 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3954 "'async smb echo handler = yes'\n"));
3955 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3956 error_to_writebrawerr(req);
3957 END_PROFILE(SMBwritebraw);
3961 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3962 if (!check_fsp(conn, req, fsp)) {
3963 error_to_writebrawerr(req);
3964 END_PROFILE(SMBwritebraw);
3968 if (!CHECK_WRITE(fsp)) {
3969 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3970 error_to_writebrawerr(req);
3971 END_PROFILE(SMBwritebraw);
3975 tcount = IVAL(req->vwv+1, 0);
3976 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3977 write_through = BITSETW(req->vwv+7,0);
3979 /* We have to deal with slightly different formats depending
3980 on whether we are using the core+ or lanman1.0 protocol */
3982 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3983 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3984 data = smb_buf_const(req->inbuf);
3986 numtowrite = SVAL(req->vwv+10, 0);
3987 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3990 /* Ensure we don't write bytes past the end of this packet. */
3991 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3993 error_to_writebrawerr(req);
3994 END_PROFILE(SMBwritebraw);
3998 if (!fsp->print_file) {
3999 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4000 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4003 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4004 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4005 error_to_writebrawerr(req);
4006 END_PROFILE(SMBwritebraw);
4012 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4015 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
4016 "wrote=%d sync=%d\n",
4017 fsp->fnum, (double)startpos, (int)numtowrite,
4018 (int)nwritten, (int)write_through));
4020 if (nwritten < (ssize_t)numtowrite) {
4021 reply_nterror(req, NT_STATUS_DISK_FULL);
4022 error_to_writebrawerr(req);
4026 total_written = nwritten;
4028 /* Allocate a buffer of 64k + length. */
4029 buf = talloc_array(NULL, char, 65540);
4031 reply_nterror(req, NT_STATUS_NO_MEMORY);
4032 error_to_writebrawerr(req);
4036 /* Return a SMBwritebraw message to the redirector to tell
4037 * it to send more bytes */
4039 memcpy(buf, req->inbuf, smb_size);
4040 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4041 SCVAL(buf,smb_com,SMBwritebraw);
4042 SSVALS(buf,smb_vwv0,0xFFFF);
4044 if (!srv_send_smb(req->sconn,
4046 false, 0, /* no signing */
4047 IS_CONN_ENCRYPTED(conn),
4049 exit_server_cleanly("reply_writebraw: srv_send_smb "
4053 /* Now read the raw data into the buffer and write it */
4054 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4056 if (!NT_STATUS_IS_OK(status)) {
4057 exit_server_cleanly("secondary writebraw failed");
4060 /* Set up outbuf to return the correct size */
4061 reply_outbuf(req, 1, 0);
4063 if (numtowrite != 0) {
4065 if (numtowrite > 0xFFFF) {
4066 DEBUG(0,("reply_writebraw: Oversize secondary write "
4067 "raw requested (%u). Terminating\n",
4068 (unsigned int)numtowrite ));
4069 exit_server_cleanly("secondary writebraw failed");
4072 if (tcount > nwritten+numtowrite) {
4073 DEBUG(3,("reply_writebraw: Client overestimated the "
4075 (int)tcount,(int)nwritten,(int)numtowrite));
4078 status = read_data(req->sconn->sock, buf+4, numtowrite);
4080 if (!NT_STATUS_IS_OK(status)) {
4081 char addr[INET6_ADDRSTRLEN];
4082 /* Try and give an error message
4083 * saying what client failed. */
4084 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4085 "raw read failed (%s) for client %s. "
4086 "Terminating\n", nt_errstr(status),
4087 get_peer_addr(req->sconn->sock, addr,
4089 exit_server_cleanly("secondary writebraw failed");
4092 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4093 if (nwritten == -1) {
4095 reply_nterror(req, map_nt_error_from_unix(errno));
4096 error_to_writebrawerr(req);
4100 if (nwritten < (ssize_t)numtowrite) {
4101 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4102 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4106 total_written += nwritten;
4111 SSVAL(req->outbuf,smb_vwv0,total_written);
4113 status = sync_file(conn, fsp, write_through);
4114 if (!NT_STATUS_IS_OK(status)) {
4115 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4116 fsp_str_dbg(fsp), nt_errstr(status)));
4117 reply_nterror(req, status);
4118 error_to_writebrawerr(req);
4122 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4124 fsp->fnum, (double)startpos, (int)numtowrite,
4125 (int)total_written));
4127 if (!fsp->print_file) {
4128 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4131 /* We won't return a status if write through is not selected - this
4132 * follows what WfWg does */
4133 END_PROFILE(SMBwritebraw);
4135 if (!write_through && total_written==tcount) {
4137 #if RABBIT_PELLET_FIX
4139 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4140 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4143 if (!send_keepalive(req->sconn->sock)) {
4144 exit_server_cleanly("reply_writebraw: send of "
4145 "keepalive failed");
4148 TALLOC_FREE(req->outbuf);
4153 if (!fsp->print_file) {
4154 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4157 END_PROFILE(SMBwritebraw);
4162 #define DBGC_CLASS DBGC_LOCKING
4164 /****************************************************************************
4165 Reply to a writeunlock (core+).
4166 ****************************************************************************/
4168 void reply_writeunlock(struct smb_request *req)
4170 connection_struct *conn = req->conn;
4171 ssize_t nwritten = -1;
4175 NTSTATUS status = NT_STATUS_OK;
4177 struct lock_struct lock;
4178 int saved_errno = 0;
4180 START_PROFILE(SMBwriteunlock);
4183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4184 END_PROFILE(SMBwriteunlock);
4188 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4190 if (!check_fsp(conn, req, fsp)) {
4191 END_PROFILE(SMBwriteunlock);
4195 if (!CHECK_WRITE(fsp)) {
4196 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4197 END_PROFILE(SMBwriteunlock);
4201 numtowrite = SVAL(req->vwv+1, 0);
4202 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4203 data = (const char *)req->buf + 3;
4205 if (!fsp->print_file && numtowrite > 0) {
4206 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4207 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4210 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4211 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4212 END_PROFILE(SMBwriteunlock);
4217 /* The special X/Open SMB protocol handling of
4218 zero length writes is *NOT* done for
4220 if(numtowrite == 0) {
4223 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4224 saved_errno = errno;
4227 status = sync_file(conn, fsp, False /* write through */);
4228 if (!NT_STATUS_IS_OK(status)) {
4229 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4230 fsp_str_dbg(fsp), nt_errstr(status)));
4231 reply_nterror(req, status);
4236 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4240 if((nwritten < numtowrite) && (numtowrite != 0)) {
4241 reply_nterror(req, NT_STATUS_DISK_FULL);
4245 if (numtowrite && !fsp->print_file) {
4246 status = do_unlock(req->sconn->msg_ctx,
4248 (uint64_t)req->smbpid,
4249 (uint64_t)numtowrite,
4253 if (NT_STATUS_V(status)) {
4254 reply_nterror(req, status);
4259 reply_outbuf(req, 1, 0);
4261 SSVAL(req->outbuf,smb_vwv0,nwritten);
4263 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4264 fsp->fnum, (int)numtowrite, (int)nwritten));
4267 if (numtowrite && !fsp->print_file) {
4268 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4271 END_PROFILE(SMBwriteunlock);
4276 #define DBGC_CLASS DBGC_ALL
4278 /****************************************************************************
4280 ****************************************************************************/
4282 void reply_write(struct smb_request *req)
4284 connection_struct *conn = req->conn;
4286 ssize_t nwritten = -1;
4290 struct lock_struct lock;
4292 int saved_errno = 0;
4294 START_PROFILE(SMBwrite);
4297 END_PROFILE(SMBwrite);
4298 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4302 /* If it's an IPC, pass off the pipe handler. */
4304 reply_pipe_write(req);
4305 END_PROFILE(SMBwrite);
4309 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4311 if (!check_fsp(conn, req, fsp)) {
4312 END_PROFILE(SMBwrite);
4316 if (!CHECK_WRITE(fsp)) {
4317 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4318 END_PROFILE(SMBwrite);
4322 numtowrite = SVAL(req->vwv+1, 0);
4323 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4324 data = (const char *)req->buf + 3;
4326 if (!fsp->print_file) {
4327 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4328 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4331 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4332 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4333 END_PROFILE(SMBwrite);
4339 * X/Open SMB protocol says that if smb_vwv1 is
4340 * zero then the file size should be extended or
4341 * truncated to the size given in smb_vwv[2-3].
4344 if(numtowrite == 0) {
4346 * This is actually an allocate call, and set EOF. JRA.
4348 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4350 reply_nterror(req, NT_STATUS_DISK_FULL);
4353 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4355 reply_nterror(req, NT_STATUS_DISK_FULL);
4358 trigger_write_time_update_immediate(fsp);
4360 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4363 status = sync_file(conn, fsp, False);
4364 if (!NT_STATUS_IS_OK(status)) {
4365 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4366 fsp_str_dbg(fsp), nt_errstr(status)));
4367 reply_nterror(req, status);
4372 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4376 if((nwritten == 0) && (numtowrite != 0)) {
4377 reply_nterror(req, NT_STATUS_DISK_FULL);
4381 reply_outbuf(req, 1, 0);
4383 SSVAL(req->outbuf,smb_vwv0,nwritten);
4385 if (nwritten < (ssize_t)numtowrite) {
4386 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4387 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4390 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4393 if (!fsp->print_file) {
4394 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4397 END_PROFILE(SMBwrite);
4401 /****************************************************************************
4402 Ensure a buffer is a valid writeX for recvfile purposes.
4403 ****************************************************************************/
4405 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4406 (2*14) + /* word count (including bcc) */ \
4409 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4410 const uint8_t *inbuf)
4413 connection_struct *conn = NULL;
4414 unsigned int doff = 0;
4415 size_t len = smb_len_large(inbuf);
4417 if (is_encrypted_packet(inbuf)) {
4418 /* Can't do this on encrypted
4423 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4427 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4428 CVAL(inbuf,smb_wct) != 14) {
4429 DEBUG(10,("is_valid_writeX_buffer: chained or "
4430 "invalid word length.\n"));
4434 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4436 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4440 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4443 if (IS_PRINT(conn)) {
4444 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4447 doff = SVAL(inbuf,smb_vwv11);
4449 numtowrite = SVAL(inbuf,smb_vwv10);
4451 if (len > doff && len - doff > 0xFFFF) {
4452 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4455 if (numtowrite == 0) {
4456 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4460 /* Ensure the sizes match up. */
4461 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4462 /* no pad byte...old smbclient :-( */
4463 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4465 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4469 if (len - doff != numtowrite) {
4470 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4471 "len = %u, doff = %u, numtowrite = %u\n",
4474 (unsigned int)numtowrite ));
4478 DEBUG(10,("is_valid_writeX_buffer: true "
4479 "len = %u, doff = %u, numtowrite = %u\n",
4482 (unsigned int)numtowrite ));
4487 /****************************************************************************
4488 Reply to a write and X.
4489 ****************************************************************************/
4491 void reply_write_and_X(struct smb_request *req)
4493 connection_struct *conn = req->conn;
4495 struct lock_struct lock;
4500 unsigned int smb_doff;
4501 unsigned int smblen;
4504 int saved_errno = 0;
4506 START_PROFILE(SMBwriteX);
4508 if ((req->wct != 12) && (req->wct != 14)) {
4509 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4510 END_PROFILE(SMBwriteX);
4514 numtowrite = SVAL(req->vwv+10, 0);
4515 smb_doff = SVAL(req->vwv+11, 0);
4516 smblen = smb_len(req->inbuf);
4518 if (req->unread_bytes > 0xFFFF ||
4519 (smblen > smb_doff &&
4520 smblen - smb_doff > 0xFFFF)) {
4521 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4524 if (req->unread_bytes) {
4525 /* Can't do a recvfile write on IPC$ */
4527 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4528 END_PROFILE(SMBwriteX);
4531 if (numtowrite != req->unread_bytes) {
4532 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4533 END_PROFILE(SMBwriteX);
4537 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4538 smb_doff + numtowrite > smblen) {
4539 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4540 END_PROFILE(SMBwriteX);
4545 /* If it's an IPC, pass off the pipe handler. */
4547 if (req->unread_bytes) {
4548 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4549 END_PROFILE(SMBwriteX);
4552 reply_pipe_write_and_X(req);
4553 END_PROFILE(SMBwriteX);
4557 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4558 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4559 write_through = BITSETW(req->vwv+7,0);
4561 if (!check_fsp(conn, req, fsp)) {
4562 END_PROFILE(SMBwriteX);
4566 if (!CHECK_WRITE(fsp)) {
4567 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4568 END_PROFILE(SMBwriteX);
4572 data = smb_base(req->inbuf) + smb_doff;
4574 if(req->wct == 14) {
4575 #ifdef LARGE_SMB_OFF_T
4577 * This is a large offset (64 bit) write.
4579 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4581 #else /* !LARGE_SMB_OFF_T */
4584 * Ensure we haven't been sent a >32 bit offset.
4587 if(IVAL(req->vwv+12, 0) != 0) {
4588 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4589 "used and we don't support 64 bit offsets.\n",
4590 (unsigned int)IVAL(req->vwv+12, 0) ));
4591 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4592 END_PROFILE(SMBwriteX);
4596 #endif /* LARGE_SMB_OFF_T */
4599 /* X/Open SMB protocol says that, unlike SMBwrite
4600 if the length is zero then NO truncation is
4601 done, just a write of zero. To truncate a file,
4604 if(numtowrite == 0) {
4607 if (req->unread_bytes == 0) {
4608 status = schedule_aio_write_and_X(conn,
4615 if (NT_STATUS_IS_OK(status)) {
4616 /* write scheduled - we're done. */
4619 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4620 /* Real error - report to client. */
4621 reply_nterror(req, status);
4624 /* NT_STATUS_RETRY - fall through to sync write. */
4627 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4628 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4631 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4632 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4636 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4637 saved_errno = errno;
4639 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4643 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4647 if((nwritten == 0) && (numtowrite != 0)) {
4648 reply_nterror(req, NT_STATUS_DISK_FULL);
4652 reply_outbuf(req, 6, 0);
4653 SSVAL(req->outbuf,smb_vwv2,nwritten);
4654 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4656 if (nwritten < (ssize_t)numtowrite) {
4657 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4658 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4661 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4662 fsp->fnum, (int)numtowrite, (int)nwritten));
4664 status = sync_file(conn, fsp, write_through);
4665 if (!NT_STATUS_IS_OK(status)) {
4666 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4667 fsp_str_dbg(fsp), nt_errstr(status)));
4668 reply_nterror(req, status);
4672 END_PROFILE(SMBwriteX);
4677 END_PROFILE(SMBwriteX);
4681 /****************************************************************************
4683 ****************************************************************************/
4685 void reply_lseek(struct smb_request *req)
4687 connection_struct *conn = req->conn;
4693 START_PROFILE(SMBlseek);
4696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4697 END_PROFILE(SMBlseek);
4701 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4703 if (!check_fsp(conn, req, fsp)) {
4707 flush_write_cache(fsp, SEEK_FLUSH);
4709 mode = SVAL(req->vwv+1, 0) & 3;
4710 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4711 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4720 res = fsp->fh->pos + startpos;
4731 if (umode == SEEK_END) {
4732 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4733 if(errno == EINVAL) {
4734 SMB_OFF_T current_pos = startpos;
4736 if(fsp_stat(fsp) == -1) {
4738 map_nt_error_from_unix(errno));
4739 END_PROFILE(SMBlseek);
4743 current_pos += fsp->fsp_name->st.st_ex_size;
4745 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4750 reply_nterror(req, map_nt_error_from_unix(errno));
4751 END_PROFILE(SMBlseek);
4758 reply_outbuf(req, 2, 0);
4759 SIVAL(req->outbuf,smb_vwv0,res);
4761 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4762 fsp->fnum, (double)startpos, (double)res, mode));
4764 END_PROFILE(SMBlseek);
4768 /****************************************************************************
4770 ****************************************************************************/
4772 void reply_flush(struct smb_request *req)
4774 connection_struct *conn = req->conn;
4778 START_PROFILE(SMBflush);
4781 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4785 fnum = SVAL(req->vwv+0, 0);
4786 fsp = file_fsp(req, fnum);
4788 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4793 file_sync_all(conn);
4795 NTSTATUS status = sync_file(conn, fsp, True);
4796 if (!NT_STATUS_IS_OK(status)) {
4797 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4798 fsp_str_dbg(fsp), nt_errstr(status)));
4799 reply_nterror(req, status);
4800 END_PROFILE(SMBflush);
4805 reply_outbuf(req, 0, 0);
4807 DEBUG(3,("flush\n"));
4808 END_PROFILE(SMBflush);
4812 /****************************************************************************
4814 conn POINTER CAN BE NULL HERE !
4815 ****************************************************************************/
4817 void reply_exit(struct smb_request *req)
4819 START_PROFILE(SMBexit);
4821 file_close_pid(req->sconn, req->smbpid, req->vuid);
4823 reply_outbuf(req, 0, 0);
4825 DEBUG(3,("exit\n"));
4827 END_PROFILE(SMBexit);
4831 /****************************************************************************
4832 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4833 ****************************************************************************/
4835 void reply_close(struct smb_request *req)
4837 connection_struct *conn = req->conn;
4838 NTSTATUS status = NT_STATUS_OK;
4839 files_struct *fsp = NULL;
4840 START_PROFILE(SMBclose);
4843 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4844 END_PROFILE(SMBclose);
4848 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4851 * We can only use check_fsp if we know it's not a directory.
4854 if (!check_fsp_open(conn, req, fsp)) {
4855 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4856 END_PROFILE(SMBclose);
4860 if(fsp->is_directory) {
4862 * Special case - close NT SMB directory handle.
4864 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4865 status = close_file(req, fsp, NORMAL_CLOSE);
4869 * Close ordinary file.
4872 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4873 fsp->fh->fd, fsp->fnum,
4874 conn->num_files_open));
4877 * Take care of any time sent in the close.
4880 t = srv_make_unix_date3(req->vwv+1);
4881 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4884 * close_file() returns the unix errno if an error
4885 * was detected on close - normally this is due to
4886 * a disk full error. If not then it was probably an I/O error.
4889 status = close_file(req, fsp, NORMAL_CLOSE);
4892 if (!NT_STATUS_IS_OK(status)) {
4893 reply_nterror(req, status);
4894 END_PROFILE(SMBclose);
4898 reply_outbuf(req, 0, 0);
4899 END_PROFILE(SMBclose);
4903 /****************************************************************************
4904 Reply to a writeclose (Core+ protocol).
4905 ****************************************************************************/
4907 void reply_writeclose(struct smb_request *req)
4909 connection_struct *conn = req->conn;
4911 ssize_t nwritten = -1;
4912 NTSTATUS close_status = NT_STATUS_OK;
4915 struct timespec mtime;
4917 struct lock_struct lock;
4919 START_PROFILE(SMBwriteclose);
4922 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4923 END_PROFILE(SMBwriteclose);
4927 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4929 if (!check_fsp(conn, req, fsp)) {
4930 END_PROFILE(SMBwriteclose);
4933 if (!CHECK_WRITE(fsp)) {
4934 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4935 END_PROFILE(SMBwriteclose);
4939 numtowrite = SVAL(req->vwv+1, 0);
4940 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4941 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4942 data = (const char *)req->buf + 1;
4944 if (!fsp->print_file) {
4945 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4946 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4949 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4950 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4951 END_PROFILE(SMBwriteclose);
4956 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4958 set_close_write_time(fsp, mtime);
4961 * More insanity. W2K only closes the file if writelen > 0.
4966 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4967 "file %s\n", fsp_str_dbg(fsp)));
4968 close_status = close_file(req, fsp, NORMAL_CLOSE);
4971 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4972 fsp->fnum, (int)numtowrite, (int)nwritten,
4973 conn->num_files_open));
4975 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4976 reply_nterror(req, NT_STATUS_DISK_FULL);
4980 if(!NT_STATUS_IS_OK(close_status)) {
4981 reply_nterror(req, close_status);
4985 reply_outbuf(req, 1, 0);
4987 SSVAL(req->outbuf,smb_vwv0,nwritten);
4990 if (numtowrite && !fsp->print_file) {
4991 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4994 END_PROFILE(SMBwriteclose);
4999 #define DBGC_CLASS DBGC_LOCKING
5001 /****************************************************************************
5003 ****************************************************************************/
5005 void reply_lock(struct smb_request *req)
5007 connection_struct *conn = req->conn;
5008 uint64_t count,offset;
5011 struct byte_range_lock *br_lck = NULL;
5013 START_PROFILE(SMBlock);
5016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5017 END_PROFILE(SMBlock);
5021 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5023 if (!check_fsp(conn, req, fsp)) {
5024 END_PROFILE(SMBlock);
5028 count = (uint64_t)IVAL(req->vwv+1, 0);
5029 offset = (uint64_t)IVAL(req->vwv+3, 0);
5031 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5032 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
5034 br_lck = do_lock(req->sconn->msg_ctx,
5036 (uint64_t)req->smbpid,
5041 False, /* Non-blocking lock. */
5046 TALLOC_FREE(br_lck);
5048 if (NT_STATUS_V(status)) {
5049 reply_nterror(req, status);
5050 END_PROFILE(SMBlock);
5054 reply_outbuf(req, 0, 0);
5056 END_PROFILE(SMBlock);
5060 /****************************************************************************
5062 ****************************************************************************/
5064 void reply_unlock(struct smb_request *req)
5066 connection_struct *conn = req->conn;
5067 uint64_t count,offset;
5071 START_PROFILE(SMBunlock);
5074 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5075 END_PROFILE(SMBunlock);
5079 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5081 if (!check_fsp(conn, req, fsp)) {
5082 END_PROFILE(SMBunlock);
5086 count = (uint64_t)IVAL(req->vwv+1, 0);
5087 offset = (uint64_t)IVAL(req->vwv+3, 0);
5089 status = do_unlock(req->sconn->msg_ctx,
5091 (uint64_t)req->smbpid,
5096 if (NT_STATUS_V(status)) {
5097 reply_nterror(req, status);
5098 END_PROFILE(SMBunlock);
5102 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5103 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5105 reply_outbuf(req, 0, 0);
5107 END_PROFILE(SMBunlock);
5112 #define DBGC_CLASS DBGC_ALL
5114 /****************************************************************************
5116 conn POINTER CAN BE NULL HERE !
5117 ****************************************************************************/
5119 void reply_tdis(struct smb_request *req)
5121 connection_struct *conn = req->conn;
5122 START_PROFILE(SMBtdis);
5125 DEBUG(4,("Invalid connection in tdis\n"));
5126 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5127 END_PROFILE(SMBtdis);
5133 close_cnum(conn,req->vuid);
5136 reply_outbuf(req, 0, 0);
5137 END_PROFILE(SMBtdis);
5141 /****************************************************************************
5143 conn POINTER CAN BE NULL HERE !
5144 ****************************************************************************/
5146 void reply_echo(struct smb_request *req)
5148 connection_struct *conn = req->conn;
5149 struct smb_perfcount_data local_pcd;
5150 struct smb_perfcount_data *cur_pcd;
5154 START_PROFILE(SMBecho);
5156 smb_init_perfcount_data(&local_pcd);
5159 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5160 END_PROFILE(SMBecho);
5164 smb_reverb = SVAL(req->vwv+0, 0);
5166 reply_outbuf(req, 1, req->buflen);
5168 /* copy any incoming data back out */
5169 if (req->buflen > 0) {
5170 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5173 if (smb_reverb > 100) {
5174 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5178 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5180 /* this makes sure we catch the request pcd */
5181 if (seq_num == smb_reverb) {
5182 cur_pcd = &req->pcd;
5184 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5185 cur_pcd = &local_pcd;
5188 SSVAL(req->outbuf,smb_vwv0,seq_num);
5190 show_msg((char *)req->outbuf);
5191 if (!srv_send_smb(req->sconn,
5192 (char *)req->outbuf,
5193 true, req->seqnum+1,
5194 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5196 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5199 DEBUG(3,("echo %d times\n", smb_reverb));
5201 TALLOC_FREE(req->outbuf);
5203 END_PROFILE(SMBecho);
5207 /****************************************************************************
5208 Reply to a printopen.
5209 ****************************************************************************/
5211 void reply_printopen(struct smb_request *req)
5213 connection_struct *conn = req->conn;
5217 START_PROFILE(SMBsplopen);
5220 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5221 END_PROFILE(SMBsplopen);
5225 if (!CAN_PRINT(conn)) {
5226 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5227 END_PROFILE(SMBsplopen);
5231 status = file_new(req, conn, &fsp);
5232 if(!NT_STATUS_IS_OK(status)) {
5233 reply_nterror(req, status);
5234 END_PROFILE(SMBsplopen);
5238 /* Open for exclusive use, write only. */
5239 status = print_spool_open(fsp, NULL, req->vuid);
5241 if (!NT_STATUS_IS_OK(status)) {
5242 file_free(req, fsp);
5243 reply_nterror(req, status);
5244 END_PROFILE(SMBsplopen);
5248 reply_outbuf(req, 1, 0);
5249 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5251 DEBUG(3,("openprint fd=%d fnum=%d\n",
5252 fsp->fh->fd, fsp->fnum));
5254 END_PROFILE(SMBsplopen);
5258 /****************************************************************************
5259 Reply to a printclose.
5260 ****************************************************************************/
5262 void reply_printclose(struct smb_request *req)
5264 connection_struct *conn = req->conn;
5268 START_PROFILE(SMBsplclose);
5271 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5272 END_PROFILE(SMBsplclose);
5276 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5278 if (!check_fsp(conn, req, fsp)) {
5279 END_PROFILE(SMBsplclose);
5283 if (!CAN_PRINT(conn)) {
5284 reply_force_doserror(req, ERRSRV, ERRerror);
5285 END_PROFILE(SMBsplclose);
5289 DEBUG(3,("printclose fd=%d fnum=%d\n",
5290 fsp->fh->fd,fsp->fnum));
5292 status = close_file(req, fsp, NORMAL_CLOSE);
5294 if(!NT_STATUS_IS_OK(status)) {
5295 reply_nterror(req, status);
5296 END_PROFILE(SMBsplclose);
5300 reply_outbuf(req, 0, 0);
5302 END_PROFILE(SMBsplclose);
5306 /****************************************************************************
5307 Reply to a printqueue.
5308 ****************************************************************************/
5310 void reply_printqueue(struct smb_request *req)
5312 connection_struct *conn = req->conn;
5316 START_PROFILE(SMBsplretq);
5319 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5320 END_PROFILE(SMBsplretq);
5324 max_count = SVAL(req->vwv+0, 0);
5325 start_index = SVAL(req->vwv+1, 0);
5327 /* we used to allow the client to get the cnum wrong, but that
5328 is really quite gross and only worked when there was only
5329 one printer - I think we should now only accept it if they
5330 get it right (tridge) */
5331 if (!CAN_PRINT(conn)) {
5332 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5333 END_PROFILE(SMBsplretq);
5337 reply_outbuf(req, 2, 3);
5338 SSVAL(req->outbuf,smb_vwv0,0);
5339 SSVAL(req->outbuf,smb_vwv1,0);
5340 SCVAL(smb_buf(req->outbuf),0,1);
5341 SSVAL(smb_buf(req->outbuf),1,0);
5343 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5344 start_index, max_count));
5347 TALLOC_CTX *mem_ctx = talloc_tos();
5350 const char *sharename = lp_servicename(SNUM(conn));
5351 struct rpc_pipe_client *cli = NULL;
5352 struct dcerpc_binding_handle *b = NULL;
5353 struct policy_handle handle;
5354 struct spoolss_DevmodeContainer devmode_ctr;
5355 union spoolss_JobInfo *info;
5357 uint32_t num_to_get;
5361 ZERO_STRUCT(handle);
5363 status = rpc_pipe_open_interface(conn,
5364 &ndr_table_spoolss.syntax_id,
5366 conn->sconn->remote_address,
5367 conn->sconn->msg_ctx,
5369 if (!NT_STATUS_IS_OK(status)) {
5370 DEBUG(0, ("reply_printqueue: "
5371 "could not connect to spoolss: %s\n",
5372 nt_errstr(status)));
5373 reply_nterror(req, status);
5376 b = cli->binding_handle;
5378 ZERO_STRUCT(devmode_ctr);
5380 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5383 SEC_FLAG_MAXIMUM_ALLOWED,
5386 if (!NT_STATUS_IS_OK(status)) {
5387 reply_nterror(req, status);
5390 if (!W_ERROR_IS_OK(werr)) {
5391 reply_nterror(req, werror_to_ntstatus(werr));
5395 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5403 if (!W_ERROR_IS_OK(werr)) {
5404 reply_nterror(req, werror_to_ntstatus(werr));
5408 if (max_count > 0) {
5409 first = start_index;
5411 first = start_index + max_count + 1;
5414 if (first >= count) {
5417 num_to_get = first + MIN(ABS(max_count), count - first);
5420 for (i = first; i < num_to_get; i++) {
5423 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5425 uint16_t qrapjobid = pjobid_to_rap(sharename,
5426 info[i].info2.job_id);
5428 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5434 srv_put_dos_date2(p, 0, qtime);
5435 SCVAL(p, 4, qstatus);
5436 SSVAL(p, 5, qrapjobid);
5437 SIVAL(p, 7, info[i].info2.size);
5439 srvstr_push(blob, req->flags2, p+12,
5440 info[i].info2.notify_name, 16, STR_ASCII);
5442 if (message_push_blob(
5445 blob, sizeof(blob))) == -1) {
5446 reply_nterror(req, NT_STATUS_NO_MEMORY);
5452 SSVAL(req->outbuf,smb_vwv0,count);
5453 SSVAL(req->outbuf,smb_vwv1,
5454 (max_count>0?first+count:first-1));
5455 SCVAL(smb_buf(req->outbuf),0,1);
5456 SSVAL(smb_buf(req->outbuf),1,28*count);
5460 DEBUG(3, ("%u entries returned in queue\n",
5464 if (b && is_valid_policy_hnd(&handle)) {
5465 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5470 END_PROFILE(SMBsplretq);
5474 /****************************************************************************
5475 Reply to a printwrite.
5476 ****************************************************************************/
5478 void reply_printwrite(struct smb_request *req)
5480 connection_struct *conn = req->conn;
5485 START_PROFILE(SMBsplwr);
5488 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5489 END_PROFILE(SMBsplwr);
5493 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5495 if (!check_fsp(conn, req, fsp)) {
5496 END_PROFILE(SMBsplwr);
5500 if (!fsp->print_file) {
5501 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5502 END_PROFILE(SMBsplwr);
5506 if (!CHECK_WRITE(fsp)) {
5507 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5508 END_PROFILE(SMBsplwr);
5512 numtowrite = SVAL(req->buf, 1);
5514 if (req->buflen < numtowrite + 3) {
5515 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5516 END_PROFILE(SMBsplwr);
5520 data = (const char *)req->buf + 3;
5522 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5523 reply_nterror(req, map_nt_error_from_unix(errno));
5524 END_PROFILE(SMBsplwr);
5528 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5530 END_PROFILE(SMBsplwr);
5534 /****************************************************************************
5536 ****************************************************************************/
5538 void reply_mkdir(struct smb_request *req)
5540 connection_struct *conn = req->conn;
5541 struct smb_filename *smb_dname = NULL;
5542 char *directory = NULL;
5544 TALLOC_CTX *ctx = talloc_tos();
5546 START_PROFILE(SMBmkdir);
5548 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5549 STR_TERMINATE, &status);
5550 if (!NT_STATUS_IS_OK(status)) {
5551 reply_nterror(req, status);
5555 status = filename_convert(ctx, conn,
5556 req->flags2 & FLAGS2_DFS_PATHNAMES,
5561 if (!NT_STATUS_IS_OK(status)) {
5562 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5563 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5564 ERRSRV, ERRbadpath);
5567 reply_nterror(req, status);
5571 status = create_directory(conn, req, smb_dname);
5573 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5575 if (!NT_STATUS_IS_OK(status)) {
5577 if (!use_nt_status()
5578 && NT_STATUS_EQUAL(status,
5579 NT_STATUS_OBJECT_NAME_COLLISION)) {
5581 * Yes, in the DOS error code case we get a
5582 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5583 * samba4 torture test.
5585 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5588 reply_nterror(req, status);
5592 reply_outbuf(req, 0, 0);
5594 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5596 TALLOC_FREE(smb_dname);
5597 END_PROFILE(SMBmkdir);
5601 /****************************************************************************
5603 ****************************************************************************/
5605 void reply_rmdir(struct smb_request *req)
5607 connection_struct *conn = req->conn;
5608 struct smb_filename *smb_dname = NULL;
5609 char *directory = NULL;
5611 TALLOC_CTX *ctx = talloc_tos();
5612 files_struct *fsp = NULL;
5614 struct smbd_server_connection *sconn = req->sconn;
5616 START_PROFILE(SMBrmdir);
5618 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5619 STR_TERMINATE, &status);
5620 if (!NT_STATUS_IS_OK(status)) {
5621 reply_nterror(req, status);
5625 status = filename_convert(ctx, conn,
5626 req->flags2 & FLAGS2_DFS_PATHNAMES,
5631 if (!NT_STATUS_IS_OK(status)) {
5632 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5633 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5634 ERRSRV, ERRbadpath);
5637 reply_nterror(req, status);
5641 if (is_ntfs_stream_smb_fname(smb_dname)) {
5642 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5646 status = SMB_VFS_CREATE_FILE(
5649 0, /* root_dir_fid */
5650 smb_dname, /* fname */
5651 DELETE_ACCESS, /* access_mask */
5652 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5654 FILE_OPEN, /* create_disposition*/
5655 FILE_DIRECTORY_FILE, /* create_options */
5656 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5657 0, /* oplock_request */
5658 0, /* allocation_size */
5659 0, /* private_flags */
5665 if (!NT_STATUS_IS_OK(status)) {
5666 if (open_was_deferred(req->mid)) {
5667 /* We have re-scheduled this call. */
5670 reply_nterror(req, status);
5674 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5675 if (!NT_STATUS_IS_OK(status)) {
5676 close_file(req, fsp, ERROR_CLOSE);
5677 reply_nterror(req, status);
5681 if (!set_delete_on_close(fsp, true, conn->session_info->unix_token)) {
5682 close_file(req, fsp, ERROR_CLOSE);
5683 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5687 status = close_file(req, fsp, NORMAL_CLOSE);
5688 if (!NT_STATUS_IS_OK(status)) {
5689 reply_nterror(req, status);
5691 reply_outbuf(req, 0, 0);
5694 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5696 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5698 TALLOC_FREE(smb_dname);
5699 END_PROFILE(SMBrmdir);
5703 /*******************************************************************
5704 Resolve wildcards in a filename rename.
5705 ********************************************************************/
5707 static bool resolve_wildcards(TALLOC_CTX *ctx,
5712 char *name2_copy = NULL;
5717 char *p,*p2, *pname1, *pname2;
5719 name2_copy = talloc_strdup(ctx, name2);
5724 pname1 = strrchr_m(name1,'/');
5725 pname2 = strrchr_m(name2_copy,'/');
5727 if (!pname1 || !pname2) {
5731 /* Truncate the copy of name2 at the last '/' */
5734 /* Now go past the '/' */
5738 root1 = talloc_strdup(ctx, pname1);
5739 root2 = talloc_strdup(ctx, pname2);
5741 if (!root1 || !root2) {
5745 p = strrchr_m(root1,'.');
5748 ext1 = talloc_strdup(ctx, p+1);
5750 ext1 = talloc_strdup(ctx, "");
5752 p = strrchr_m(root2,'.');
5755 ext2 = talloc_strdup(ctx, p+1);
5757 ext2 = talloc_strdup(ctx, "");
5760 if (!ext1 || !ext2) {
5768 /* Hmmm. Should this be mb-aware ? */
5771 } else if (*p2 == '*') {
5773 root2 = talloc_asprintf(ctx, "%s%s",
5792 /* Hmmm. Should this be mb-aware ? */
5795 } else if (*p2 == '*') {
5797 ext2 = talloc_asprintf(ctx, "%s%s",
5813 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5818 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5830 /****************************************************************************
5831 Ensure open files have their names updated. Updated to notify other smbd's
5833 ****************************************************************************/
5835 static void rename_open_files(connection_struct *conn,
5836 struct share_mode_lock *lck,
5837 uint32_t orig_name_hash,
5838 const struct smb_filename *smb_fname_dst)
5841 bool did_rename = False;
5843 uint32_t new_name_hash = 0;
5845 for(fsp = file_find_di_first(conn->sconn, lck->id); fsp;
5846 fsp = file_find_di_next(fsp)) {
5847 /* fsp_name is a relative path under the fsp. To change this for other
5848 sharepaths we need to manipulate relative paths. */
5849 /* TODO - create the absolute path and manipulate the newname
5850 relative to the sharepath. */
5851 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5854 if (fsp->name_hash != orig_name_hash) {
5857 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5858 "(file_id %s) from %s -> %s\n", fsp->fnum,
5859 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5860 smb_fname_str_dbg(smb_fname_dst)));
5862 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5863 if (NT_STATUS_IS_OK(status)) {
5865 new_name_hash = fsp->name_hash;
5870 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5871 "for %s\n", file_id_string_tos(&lck->id),
5872 smb_fname_str_dbg(smb_fname_dst)));
5875 /* Send messages to all smbd's (not ourself) that the name has changed. */
5876 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5877 orig_name_hash, new_name_hash,
5882 /****************************************************************************
5883 We need to check if the source path is a parent directory of the destination
5884 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5885 refuse the rename with a sharing violation. Under UNIX the above call can
5886 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5887 probably need to check that the client is a Windows one before disallowing
5888 this as a UNIX client (one with UNIX extensions) can know the source is a
5889 symlink and make this decision intelligently. Found by an excellent bug
5890 report from <AndyLiebman@aol.com>.
5891 ****************************************************************************/
5893 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5894 const struct smb_filename *smb_fname_dst)
5896 const char *psrc = smb_fname_src->base_name;
5897 const char *pdst = smb_fname_dst->base_name;
5900 if (psrc[0] == '.' && psrc[1] == '/') {
5903 if (pdst[0] == '.' && pdst[1] == '/') {
5906 if ((slen = strlen(psrc)) > strlen(pdst)) {
5909 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5913 * Do the notify calls from a rename
5916 static void notify_rename(connection_struct *conn, bool is_dir,
5917 const struct smb_filename *smb_fname_src,
5918 const struct smb_filename *smb_fname_dst)
5920 char *parent_dir_src = NULL;
5921 char *parent_dir_dst = NULL;
5924 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5925 : FILE_NOTIFY_CHANGE_FILE_NAME;
5927 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5928 &parent_dir_src, NULL) ||
5929 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5930 &parent_dir_dst, NULL)) {
5934 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5935 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5936 smb_fname_src->base_name);
5937 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5938 smb_fname_dst->base_name);
5941 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5942 smb_fname_src->base_name);
5943 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5944 smb_fname_dst->base_name);
5947 /* this is a strange one. w2k3 gives an additional event for
5948 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5949 files, but not directories */
5951 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5952 FILE_NOTIFY_CHANGE_ATTRIBUTES
5953 |FILE_NOTIFY_CHANGE_CREATION,
5954 smb_fname_dst->base_name);
5957 TALLOC_FREE(parent_dir_src);
5958 TALLOC_FREE(parent_dir_dst);
5961 /****************************************************************************
5962 Rename an open file - given an fsp.
5963 ****************************************************************************/
5965 NTSTATUS rename_internals_fsp(connection_struct *conn,
5967 const struct smb_filename *smb_fname_dst_in,
5969 bool replace_if_exists)
5971 TALLOC_CTX *ctx = talloc_tos();
5972 struct smb_filename *smb_fname_dst = NULL;
5973 NTSTATUS status = NT_STATUS_OK;
5974 struct share_mode_lock *lck = NULL;
5975 bool dst_exists, old_is_stream, new_is_stream;
5977 status = check_name(conn, smb_fname_dst_in->base_name);
5978 if (!NT_STATUS_IS_OK(status)) {
5982 /* Make a copy of the dst smb_fname structs */
5984 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5985 if (!NT_STATUS_IS_OK(status)) {
5990 * Check for special case with case preserving and not
5991 * case sensitive. If the old last component differs from the original
5992 * last component only by case, then we should allow
5993 * the rename (user is trying to change the case of the
5996 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5997 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5998 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6000 char *fname_dst_lcomp_base_mod = NULL;
6001 struct smb_filename *smb_fname_orig_lcomp = NULL;
6004 * Get the last component of the destination name.
6006 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6008 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6010 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6012 if (!fname_dst_lcomp_base_mod) {
6013 status = NT_STATUS_NO_MEMORY;
6018 * Create an smb_filename struct using the original last
6019 * component of the destination.
6021 status = create_synthetic_smb_fname_split(ctx,
6022 smb_fname_dst->original_lcomp, NULL,
6023 &smb_fname_orig_lcomp);
6024 if (!NT_STATUS_IS_OK(status)) {
6025 TALLOC_FREE(fname_dst_lcomp_base_mod);
6029 /* If the base names only differ by case, use original. */
6030 if(!strcsequal(fname_dst_lcomp_base_mod,
6031 smb_fname_orig_lcomp->base_name)) {
6034 * Replace the modified last component with the
6038 *last_slash = '\0'; /* Truncate at the '/' */
6039 tmp = talloc_asprintf(smb_fname_dst,
6041 smb_fname_dst->base_name,
6042 smb_fname_orig_lcomp->base_name);
6044 tmp = talloc_asprintf(smb_fname_dst,
6046 smb_fname_orig_lcomp->base_name);
6049 status = NT_STATUS_NO_MEMORY;
6050 TALLOC_FREE(fname_dst_lcomp_base_mod);
6051 TALLOC_FREE(smb_fname_orig_lcomp);
6054 TALLOC_FREE(smb_fname_dst->base_name);
6055 smb_fname_dst->base_name = tmp;
6058 /* If the stream_names only differ by case, use original. */
6059 if(!strcsequal(smb_fname_dst->stream_name,
6060 smb_fname_orig_lcomp->stream_name)) {
6062 /* Use the original stream. */
6063 tmp = talloc_strdup(smb_fname_dst,
6064 smb_fname_orig_lcomp->stream_name);
6066 status = NT_STATUS_NO_MEMORY;
6067 TALLOC_FREE(fname_dst_lcomp_base_mod);
6068 TALLOC_FREE(smb_fname_orig_lcomp);
6071 TALLOC_FREE(smb_fname_dst->stream_name);
6072 smb_fname_dst->stream_name = tmp;
6074 TALLOC_FREE(fname_dst_lcomp_base_mod);
6075 TALLOC_FREE(smb_fname_orig_lcomp);
6079 * If the src and dest names are identical - including case,
6080 * don't do the rename, just return success.
6083 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6084 strcsequal(fsp->fsp_name->stream_name,
6085 smb_fname_dst->stream_name)) {
6086 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6087 "- returning success\n",
6088 smb_fname_str_dbg(smb_fname_dst)));
6089 status = NT_STATUS_OK;
6093 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6094 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6096 /* Return the correct error code if both names aren't streams. */
6097 if (!old_is_stream && new_is_stream) {
6098 status = NT_STATUS_OBJECT_NAME_INVALID;
6102 if (old_is_stream && !new_is_stream) {
6103 status = NT_STATUS_INVALID_PARAMETER;
6107 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6109 if(!replace_if_exists && dst_exists) {
6110 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6111 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6112 smb_fname_str_dbg(smb_fname_dst)));
6113 status = NT_STATUS_OBJECT_NAME_COLLISION;
6118 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6119 &smb_fname_dst->st);
6120 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6122 /* The file can be open when renaming a stream */
6123 if (dst_fsp && !new_is_stream) {
6124 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6125 status = NT_STATUS_ACCESS_DENIED;
6130 /* Ensure we have a valid stat struct for the source. */
6131 status = vfs_stat_fsp(fsp);
6132 if (!NT_STATUS_IS_OK(status)) {
6136 status = can_rename(conn, fsp, attrs);
6138 if (!NT_STATUS_IS_OK(status)) {
6139 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6140 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6141 smb_fname_str_dbg(smb_fname_dst)));
6142 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6143 status = NT_STATUS_ACCESS_DENIED;
6147 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6148 status = NT_STATUS_ACCESS_DENIED;
6151 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6155 * We have the file open ourselves, so not being able to get the
6156 * corresponding share mode lock is a fatal error.
6159 SMB_ASSERT(lck != NULL);
6161 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6162 uint32 create_options = fsp->fh->private_options;
6164 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6165 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6166 smb_fname_str_dbg(smb_fname_dst)));
6168 if (!lp_posix_pathnames() &&
6169 (lp_map_archive(SNUM(conn)) ||
6170 lp_store_dos_attributes(SNUM(conn)))) {
6171 /* We must set the archive bit on the newly
6173 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6174 uint32_t old_dosmode = dos_mode(conn,
6176 file_set_dosmode(conn,
6178 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6184 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6187 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6190 * A rename acts as a new file create w.r.t. allowing an initial delete
6191 * on close, probably because in Windows there is a new handle to the
6192 * new file. If initial delete on close was requested but not
6193 * originally set, we need to set it here. This is probably not 100% correct,
6194 * but will work for the CIFSFS client which in non-posix mode
6195 * depends on these semantics. JRA.
6198 if (create_options & FILE_DELETE_ON_CLOSE) {
6199 status = can_set_delete_on_close(fsp, 0);
6201 if (NT_STATUS_IS_OK(status)) {
6202 /* Note that here we set the *inital* delete on close flag,
6203 * not the regular one. The magic gets handled in close. */
6204 fsp->initial_delete_on_close = True;
6208 status = NT_STATUS_OK;
6214 if (errno == ENOTDIR || errno == EISDIR) {
6215 status = NT_STATUS_OBJECT_NAME_COLLISION;
6217 status = map_nt_error_from_unix(errno);
6220 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6221 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6222 smb_fname_str_dbg(smb_fname_dst)));
6225 TALLOC_FREE(smb_fname_dst);
6230 /****************************************************************************
6231 The guts of the rename command, split out so it may be called by the NT SMB
6233 ****************************************************************************/
6235 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6236 connection_struct *conn,
6237 struct smb_request *req,
6238 struct smb_filename *smb_fname_src,
6239 struct smb_filename *smb_fname_dst,
6241 bool replace_if_exists,
6244 uint32_t access_mask)
6246 char *fname_src_dir = NULL;
6247 char *fname_src_mask = NULL;
6249 NTSTATUS status = NT_STATUS_OK;
6250 struct smb_Dir *dir_hnd = NULL;
6251 const char *dname = NULL;
6252 char *talloced = NULL;
6254 int create_options = 0;
6255 bool posix_pathnames = lp_posix_pathnames();
6258 * Split the old name into directory and last component
6259 * strings. Note that unix_convert may have stripped off a
6260 * leading ./ from both name and newname if the rename is
6261 * at the root of the share. We need to make sure either both
6262 * name and newname contain a / character or neither of them do
6263 * as this is checked in resolve_wildcards().
6266 /* Split up the directory from the filename/mask. */
6267 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6268 &fname_src_dir, &fname_src_mask);
6269 if (!NT_STATUS_IS_OK(status)) {
6270 status = NT_STATUS_NO_MEMORY;
6275 * We should only check the mangled cache
6276 * here if unix_convert failed. This means
6277 * that the path in 'mask' doesn't exist
6278 * on the file system and so we need to look
6279 * for a possible mangle. This patch from
6280 * Tine Smukavec <valentin.smukavec@hermes.si>.
6283 if (!VALID_STAT(smb_fname_src->st) &&
6284 mangle_is_mangled(fname_src_mask, conn->params)) {
6285 char *new_mask = NULL;
6286 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6289 TALLOC_FREE(fname_src_mask);
6290 fname_src_mask = new_mask;
6294 if (!src_has_wild) {
6298 * Only one file needs to be renamed. Append the mask back
6299 * onto the directory.
6301 TALLOC_FREE(smb_fname_src->base_name);
6302 if (ISDOT(fname_src_dir)) {
6303 /* Ensure we use canonical names on open. */
6304 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6308 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6313 if (!smb_fname_src->base_name) {
6314 status = NT_STATUS_NO_MEMORY;
6318 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6319 "case_preserve = %d, short case preserve = %d, "
6320 "directory = %s, newname = %s, "
6321 "last_component_dest = %s\n",
6322 conn->case_sensitive, conn->case_preserve,
6323 conn->short_case_preserve,
6324 smb_fname_str_dbg(smb_fname_src),
6325 smb_fname_str_dbg(smb_fname_dst),
6326 smb_fname_dst->original_lcomp));
6328 /* The dest name still may have wildcards. */
6329 if (dest_has_wild) {
6330 char *fname_dst_mod = NULL;
6331 if (!resolve_wildcards(smb_fname_dst,
6332 smb_fname_src->base_name,
6333 smb_fname_dst->base_name,
6335 DEBUG(6, ("rename_internals: resolve_wildcards "
6337 smb_fname_src->base_name,
6338 smb_fname_dst->base_name));
6339 status = NT_STATUS_NO_MEMORY;
6342 TALLOC_FREE(smb_fname_dst->base_name);
6343 smb_fname_dst->base_name = fname_dst_mod;
6346 ZERO_STRUCT(smb_fname_src->st);
6347 if (posix_pathnames) {
6348 SMB_VFS_LSTAT(conn, smb_fname_src);
6350 SMB_VFS_STAT(conn, smb_fname_src);
6353 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6354 create_options |= FILE_DIRECTORY_FILE;
6357 status = SMB_VFS_CREATE_FILE(
6360 0, /* root_dir_fid */
6361 smb_fname_src, /* fname */
6362 access_mask, /* access_mask */
6363 (FILE_SHARE_READ | /* share_access */
6365 FILE_OPEN, /* create_disposition*/
6366 create_options, /* create_options */
6367 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6368 0, /* oplock_request */
6369 0, /* allocation_size */
6370 0, /* private_flags */
6376 if (!NT_STATUS_IS_OK(status)) {
6377 DEBUG(3, ("Could not open rename source %s: %s\n",
6378 smb_fname_str_dbg(smb_fname_src),
6379 nt_errstr(status)));
6383 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6384 attrs, replace_if_exists);
6386 close_file(req, fsp, NORMAL_CLOSE);
6388 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6389 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6390 smb_fname_str_dbg(smb_fname_dst)));
6396 * Wildcards - process each file that matches.
6398 if (strequal(fname_src_mask, "????????.???")) {
6399 TALLOC_FREE(fname_src_mask);
6400 fname_src_mask = talloc_strdup(ctx, "*");
6401 if (!fname_src_mask) {
6402 status = NT_STATUS_NO_MEMORY;
6407 status = check_name(conn, fname_src_dir);
6408 if (!NT_STATUS_IS_OK(status)) {
6412 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6414 if (dir_hnd == NULL) {
6415 status = map_nt_error_from_unix(errno);
6419 status = NT_STATUS_NO_SUCH_FILE;
6421 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6422 * - gentest fix. JRA
6425 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6427 files_struct *fsp = NULL;
6428 char *destname = NULL;
6429 bool sysdir_entry = False;
6431 /* Quick check for "." and ".." */
6432 if (ISDOT(dname) || ISDOTDOT(dname)) {
6433 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6434 sysdir_entry = True;
6436 TALLOC_FREE(talloced);
6441 if (!is_visible_file(conn, fname_src_dir, dname,
6442 &smb_fname_src->st, false)) {
6443 TALLOC_FREE(talloced);
6447 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6448 TALLOC_FREE(talloced);
6453 status = NT_STATUS_OBJECT_NAME_INVALID;
6457 TALLOC_FREE(smb_fname_src->base_name);
6458 if (ISDOT(fname_src_dir)) {
6459 /* Ensure we use canonical names on open. */
6460 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6464 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6469 if (!smb_fname_src->base_name) {
6470 status = NT_STATUS_NO_MEMORY;
6474 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6475 smb_fname_dst->base_name,
6477 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6478 smb_fname_src->base_name, destname));
6479 TALLOC_FREE(talloced);
6483 status = NT_STATUS_NO_MEMORY;
6487 TALLOC_FREE(smb_fname_dst->base_name);
6488 smb_fname_dst->base_name = destname;
6490 ZERO_STRUCT(smb_fname_src->st);
6491 if (posix_pathnames) {
6492 SMB_VFS_LSTAT(conn, smb_fname_src);
6494 SMB_VFS_STAT(conn, smb_fname_src);
6499 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6500 create_options |= FILE_DIRECTORY_FILE;
6503 status = SMB_VFS_CREATE_FILE(
6506 0, /* root_dir_fid */
6507 smb_fname_src, /* fname */
6508 access_mask, /* access_mask */
6509 (FILE_SHARE_READ | /* share_access */
6511 FILE_OPEN, /* create_disposition*/
6512 create_options, /* create_options */
6513 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6514 0, /* oplock_request */
6515 0, /* allocation_size */
6516 0, /* private_flags */
6522 if (!NT_STATUS_IS_OK(status)) {
6523 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6524 "returned %s rename %s -> %s\n",
6526 smb_fname_str_dbg(smb_fname_src),
6527 smb_fname_str_dbg(smb_fname_dst)));
6531 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6533 if (!smb_fname_dst->original_lcomp) {
6534 status = NT_STATUS_NO_MEMORY;
6538 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6539 attrs, replace_if_exists);
6541 close_file(req, fsp, NORMAL_CLOSE);
6543 if (!NT_STATUS_IS_OK(status)) {
6544 DEBUG(3, ("rename_internals_fsp returned %s for "
6545 "rename %s -> %s\n", nt_errstr(status),
6546 smb_fname_str_dbg(smb_fname_src),
6547 smb_fname_str_dbg(smb_fname_dst)));
6553 DEBUG(3,("rename_internals: doing rename on %s -> "
6554 "%s\n", smb_fname_str_dbg(smb_fname_src),
6555 smb_fname_str_dbg(smb_fname_src)));
6556 TALLOC_FREE(talloced);
6558 TALLOC_FREE(dir_hnd);
6560 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6561 status = map_nt_error_from_unix(errno);
6565 TALLOC_FREE(talloced);
6566 TALLOC_FREE(fname_src_dir);
6567 TALLOC_FREE(fname_src_mask);
6571 /****************************************************************************
6573 ****************************************************************************/
6575 void reply_mv(struct smb_request *req)
6577 connection_struct *conn = req->conn;
6579 char *newname = NULL;
6583 bool src_has_wcard = False;
6584 bool dest_has_wcard = False;
6585 TALLOC_CTX *ctx = talloc_tos();
6586 struct smb_filename *smb_fname_src = NULL;
6587 struct smb_filename *smb_fname_dst = NULL;
6588 bool stream_rename = false;
6590 START_PROFILE(SMBmv);
6593 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6597 attrs = SVAL(req->vwv+0, 0);
6599 p = (const char *)req->buf + 1;
6600 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6601 &status, &src_has_wcard);
6602 if (!NT_STATUS_IS_OK(status)) {
6603 reply_nterror(req, status);
6607 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6608 &status, &dest_has_wcard);
6609 if (!NT_STATUS_IS_OK(status)) {
6610 reply_nterror(req, status);
6614 if (!lp_posix_pathnames()) {
6615 /* The newname must begin with a ':' if the
6616 name contains a ':'. */
6617 if (strchr_m(name, ':')) {
6618 if (newname[0] != ':') {
6619 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6622 stream_rename = true;
6626 status = filename_convert(ctx,
6628 req->flags2 & FLAGS2_DFS_PATHNAMES,
6630 UCF_COND_ALLOW_WCARD_LCOMP,
6634 if (!NT_STATUS_IS_OK(status)) {
6635 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6636 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6637 ERRSRV, ERRbadpath);
6640 reply_nterror(req, status);
6644 status = filename_convert(ctx,
6646 req->flags2 & FLAGS2_DFS_PATHNAMES,
6648 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6652 if (!NT_STATUS_IS_OK(status)) {
6653 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6654 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6655 ERRSRV, ERRbadpath);
6658 reply_nterror(req, status);
6662 if (stream_rename) {
6663 /* smb_fname_dst->base_name must be the same as
6664 smb_fname_src->base_name. */
6665 TALLOC_FREE(smb_fname_dst->base_name);
6666 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6667 smb_fname_src->base_name);
6668 if (!smb_fname_dst->base_name) {
6669 reply_nterror(req, NT_STATUS_NO_MEMORY);
6674 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6675 smb_fname_str_dbg(smb_fname_dst)));
6677 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6678 attrs, False, src_has_wcard, dest_has_wcard,
6680 if (!NT_STATUS_IS_OK(status)) {
6681 if (open_was_deferred(req->mid)) {
6682 /* We have re-scheduled this call. */
6685 reply_nterror(req, status);
6689 reply_outbuf(req, 0, 0);
6691 TALLOC_FREE(smb_fname_src);
6692 TALLOC_FREE(smb_fname_dst);
6697 /*******************************************************************
6698 Copy a file as part of a reply_copy.
6699 ******************************************************************/
6702 * TODO: check error codes on all callers
6705 NTSTATUS copy_file(TALLOC_CTX *ctx,
6706 connection_struct *conn,
6707 struct smb_filename *smb_fname_src,
6708 struct smb_filename *smb_fname_dst,
6711 bool target_is_directory)
6713 struct smb_filename *smb_fname_dst_tmp = NULL;
6715 files_struct *fsp1,*fsp2;
6717 uint32 new_create_disposition;
6721 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6722 if (!NT_STATUS_IS_OK(status)) {
6727 * If the target is a directory, extract the last component from the
6728 * src filename and append it to the dst filename
6730 if (target_is_directory) {
6733 /* dest/target can't be a stream if it's a directory. */
6734 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6736 p = strrchr_m(smb_fname_src->base_name,'/');
6740 p = smb_fname_src->base_name;
6742 smb_fname_dst_tmp->base_name =
6743 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6745 if (!smb_fname_dst_tmp->base_name) {
6746 status = NT_STATUS_NO_MEMORY;
6751 status = vfs_file_exist(conn, smb_fname_src);
6752 if (!NT_STATUS_IS_OK(status)) {
6756 if (!target_is_directory && count) {
6757 new_create_disposition = FILE_OPEN;
6759 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6762 &new_create_disposition,
6765 status = NT_STATUS_INVALID_PARAMETER;
6770 /* Open the src file for reading. */
6771 status = SMB_VFS_CREATE_FILE(
6774 0, /* root_dir_fid */
6775 smb_fname_src, /* fname */
6776 FILE_GENERIC_READ, /* access_mask */
6777 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6778 FILE_OPEN, /* create_disposition*/
6779 0, /* create_options */
6780 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6781 INTERNAL_OPEN_ONLY, /* oplock_request */
6782 0, /* allocation_size */
6783 0, /* private_flags */
6789 if (!NT_STATUS_IS_OK(status)) {
6793 dosattrs = dos_mode(conn, smb_fname_src);
6795 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6796 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6799 /* Open the dst file for writing. */
6800 status = SMB_VFS_CREATE_FILE(
6803 0, /* root_dir_fid */
6804 smb_fname_dst, /* fname */
6805 FILE_GENERIC_WRITE, /* access_mask */
6806 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6807 new_create_disposition, /* create_disposition*/
6808 0, /* create_options */
6809 dosattrs, /* file_attributes */
6810 INTERNAL_OPEN_ONLY, /* oplock_request */
6811 0, /* allocation_size */
6812 0, /* private_flags */
6818 if (!NT_STATUS_IS_OK(status)) {
6819 close_file(NULL, fsp1, ERROR_CLOSE);
6823 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6824 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6826 DEBUG(0, ("error - vfs lseek returned error %s\n",
6828 status = map_nt_error_from_unix(errno);
6829 close_file(NULL, fsp1, ERROR_CLOSE);
6830 close_file(NULL, fsp2, ERROR_CLOSE);
6835 /* Do the actual copy. */
6836 if (smb_fname_src->st.st_ex_size) {
6837 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6842 close_file(NULL, fsp1, NORMAL_CLOSE);
6844 /* Ensure the modtime is set correctly on the destination file. */
6845 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6848 * As we are opening fsp1 read-only we only expect
6849 * an error on close on fsp2 if we are out of space.
6850 * Thus we don't look at the error return from the
6853 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6855 if (!NT_STATUS_IS_OK(status)) {
6859 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6860 status = NT_STATUS_DISK_FULL;
6864 status = NT_STATUS_OK;
6867 TALLOC_FREE(smb_fname_dst_tmp);
6871 /****************************************************************************
6872 Reply to a file copy.
6873 ****************************************************************************/
6875 void reply_copy(struct smb_request *req)
6877 connection_struct *conn = req->conn;
6878 struct smb_filename *smb_fname_src = NULL;
6879 struct smb_filename *smb_fname_dst = NULL;
6880 char *fname_src = NULL;
6881 char *fname_dst = NULL;
6882 char *fname_src_mask = NULL;
6883 char *fname_src_dir = NULL;
6886 int error = ERRnoaccess;
6890 bool target_is_directory=False;
6891 bool source_has_wild = False;
6892 bool dest_has_wild = False;
6894 TALLOC_CTX *ctx = talloc_tos();
6896 START_PROFILE(SMBcopy);
6899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6903 tid2 = SVAL(req->vwv+0, 0);
6904 ofun = SVAL(req->vwv+1, 0);
6905 flags = SVAL(req->vwv+2, 0);
6907 p = (const char *)req->buf;
6908 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6909 &status, &source_has_wild);
6910 if (!NT_STATUS_IS_OK(status)) {
6911 reply_nterror(req, status);
6914 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6915 &status, &dest_has_wild);
6916 if (!NT_STATUS_IS_OK(status)) {
6917 reply_nterror(req, status);
6921 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6923 if (tid2 != conn->cnum) {
6924 /* can't currently handle inter share copies XXXX */
6925 DEBUG(3,("Rejecting inter-share copy\n"));
6926 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6930 status = filename_convert(ctx, conn,
6931 req->flags2 & FLAGS2_DFS_PATHNAMES,
6933 UCF_COND_ALLOW_WCARD_LCOMP,
6936 if (!NT_STATUS_IS_OK(status)) {
6937 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6938 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6939 ERRSRV, ERRbadpath);
6942 reply_nterror(req, status);
6946 status = filename_convert(ctx, conn,
6947 req->flags2 & FLAGS2_DFS_PATHNAMES,
6949 UCF_COND_ALLOW_WCARD_LCOMP,
6952 if (!NT_STATUS_IS_OK(status)) {
6953 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6954 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6955 ERRSRV, ERRbadpath);
6958 reply_nterror(req, status);
6962 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6964 if ((flags&1) && target_is_directory) {
6965 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6969 if ((flags&2) && !target_is_directory) {
6970 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6974 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6975 /* wants a tree copy! XXXX */
6976 DEBUG(3,("Rejecting tree copy\n"));
6977 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6981 /* Split up the directory from the filename/mask. */
6982 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6983 &fname_src_dir, &fname_src_mask);
6984 if (!NT_STATUS_IS_OK(status)) {
6985 reply_nterror(req, NT_STATUS_NO_MEMORY);
6990 * We should only check the mangled cache
6991 * here if unix_convert failed. This means
6992 * that the path in 'mask' doesn't exist
6993 * on the file system and so we need to look
6994 * for a possible mangle. This patch from
6995 * Tine Smukavec <valentin.smukavec@hermes.si>.
6997 if (!VALID_STAT(smb_fname_src->st) &&
6998 mangle_is_mangled(fname_src_mask, conn->params)) {
6999 char *new_mask = NULL;
7000 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7001 &new_mask, conn->params);
7003 /* Use demangled name if one was successfully found. */
7005 TALLOC_FREE(fname_src_mask);
7006 fname_src_mask = new_mask;
7010 if (!source_has_wild) {
7013 * Only one file needs to be copied. Append the mask back onto
7016 TALLOC_FREE(smb_fname_src->base_name);
7017 if (ISDOT(fname_src_dir)) {
7018 /* Ensure we use canonical names on open. */
7019 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7023 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7028 if (!smb_fname_src->base_name) {
7029 reply_nterror(req, NT_STATUS_NO_MEMORY);
7033 if (dest_has_wild) {
7034 char *fname_dst_mod = NULL;
7035 if (!resolve_wildcards(smb_fname_dst,
7036 smb_fname_src->base_name,
7037 smb_fname_dst->base_name,
7039 reply_nterror(req, NT_STATUS_NO_MEMORY);
7042 TALLOC_FREE(smb_fname_dst->base_name);
7043 smb_fname_dst->base_name = fname_dst_mod;
7046 status = check_name(conn, smb_fname_src->base_name);
7047 if (!NT_STATUS_IS_OK(status)) {
7048 reply_nterror(req, status);
7052 status = check_name(conn, smb_fname_dst->base_name);
7053 if (!NT_STATUS_IS_OK(status)) {
7054 reply_nterror(req, status);
7058 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7059 ofun, count, target_is_directory);
7061 if(!NT_STATUS_IS_OK(status)) {
7062 reply_nterror(req, status);
7068 struct smb_Dir *dir_hnd = NULL;
7069 const char *dname = NULL;
7070 char *talloced = NULL;
7074 * There is a wildcard that requires us to actually read the
7075 * src dir and copy each file matching the mask to the dst.
7076 * Right now streams won't be copied, but this could
7077 * presumably be added with a nested loop for reach dir entry.
7079 SMB_ASSERT(!smb_fname_src->stream_name);
7080 SMB_ASSERT(!smb_fname_dst->stream_name);
7082 smb_fname_src->stream_name = NULL;
7083 smb_fname_dst->stream_name = NULL;
7085 if (strequal(fname_src_mask,"????????.???")) {
7086 TALLOC_FREE(fname_src_mask);
7087 fname_src_mask = talloc_strdup(ctx, "*");
7088 if (!fname_src_mask) {
7089 reply_nterror(req, NT_STATUS_NO_MEMORY);
7094 status = check_name(conn, fname_src_dir);
7095 if (!NT_STATUS_IS_OK(status)) {
7096 reply_nterror(req, status);
7100 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7101 if (dir_hnd == NULL) {
7102 status = map_nt_error_from_unix(errno);
7103 reply_nterror(req, status);
7109 /* Iterate over the src dir copying each entry to the dst. */
7110 while ((dname = ReadDirName(dir_hnd, &offset,
7111 &smb_fname_src->st, &talloced))) {
7112 char *destname = NULL;
7114 if (ISDOT(dname) || ISDOTDOT(dname)) {
7115 TALLOC_FREE(talloced);
7119 if (!is_visible_file(conn, fname_src_dir, dname,
7120 &smb_fname_src->st, false)) {
7121 TALLOC_FREE(talloced);
7125 if(!mask_match(dname, fname_src_mask,
7126 conn->case_sensitive)) {
7127 TALLOC_FREE(talloced);
7131 error = ERRnoaccess;
7133 /* Get the src smb_fname struct setup. */
7134 TALLOC_FREE(smb_fname_src->base_name);
7135 if (ISDOT(fname_src_dir)) {
7136 /* Ensure we use canonical names on open. */
7137 smb_fname_src->base_name =
7138 talloc_asprintf(smb_fname_src, "%s",
7141 smb_fname_src->base_name =
7142 talloc_asprintf(smb_fname_src, "%s/%s",
7143 fname_src_dir, dname);
7146 if (!smb_fname_src->base_name) {
7147 TALLOC_FREE(dir_hnd);
7148 TALLOC_FREE(talloced);
7149 reply_nterror(req, NT_STATUS_NO_MEMORY);
7153 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7154 smb_fname_dst->base_name,
7156 TALLOC_FREE(talloced);
7160 TALLOC_FREE(dir_hnd);
7161 TALLOC_FREE(talloced);
7162 reply_nterror(req, NT_STATUS_NO_MEMORY);
7166 TALLOC_FREE(smb_fname_dst->base_name);
7167 smb_fname_dst->base_name = destname;
7169 status = check_name(conn, smb_fname_src->base_name);
7170 if (!NT_STATUS_IS_OK(status)) {
7171 TALLOC_FREE(dir_hnd);
7172 TALLOC_FREE(talloced);
7173 reply_nterror(req, status);
7177 status = check_name(conn, smb_fname_dst->base_name);
7178 if (!NT_STATUS_IS_OK(status)) {
7179 TALLOC_FREE(dir_hnd);
7180 TALLOC_FREE(talloced);
7181 reply_nterror(req, status);
7185 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7186 smb_fname_src->base_name,
7187 smb_fname_dst->base_name));
7189 status = copy_file(ctx, conn, smb_fname_src,
7190 smb_fname_dst, ofun, count,
7191 target_is_directory);
7192 if (NT_STATUS_IS_OK(status)) {
7196 TALLOC_FREE(talloced);
7198 TALLOC_FREE(dir_hnd);
7202 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7206 reply_outbuf(req, 1, 0);
7207 SSVAL(req->outbuf,smb_vwv0,count);
7209 TALLOC_FREE(smb_fname_src);
7210 TALLOC_FREE(smb_fname_dst);
7211 TALLOC_FREE(fname_src);
7212 TALLOC_FREE(fname_dst);
7213 TALLOC_FREE(fname_src_mask);
7214 TALLOC_FREE(fname_src_dir);
7216 END_PROFILE(SMBcopy);
7221 #define DBGC_CLASS DBGC_LOCKING
7223 /****************************************************************************
7224 Get a lock pid, dealing with large count requests.
7225 ****************************************************************************/
7227 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7228 bool large_file_format)
7230 if(!large_file_format)
7231 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7233 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7236 /****************************************************************************
7237 Get a lock count, dealing with large count requests.
7238 ****************************************************************************/
7240 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7241 bool large_file_format)
7245 if(!large_file_format) {
7246 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7249 #if defined(HAVE_LONGLONG)
7250 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7251 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7252 #else /* HAVE_LONGLONG */
7255 * NT4.x seems to be broken in that it sends large file (64 bit)
7256 * lockingX calls even if the CAP_LARGE_FILES was *not*
7257 * negotiated. For boxes without large unsigned ints truncate the
7258 * lock count by dropping the top 32 bits.
7261 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7262 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7263 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7264 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7265 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7268 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7269 #endif /* HAVE_LONGLONG */
7275 #if !defined(HAVE_LONGLONG)
7276 /****************************************************************************
7277 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7278 ****************************************************************************/
7280 static uint32 map_lock_offset(uint32 high, uint32 low)
7284 uint32 highcopy = high;
7287 * Try and find out how many significant bits there are in high.
7290 for(i = 0; highcopy; i++)
7294 * We use 31 bits not 32 here as POSIX
7295 * lock offsets may not be negative.
7298 mask = (~0) << (31 - i);
7301 return 0; /* Fail. */
7307 #endif /* !defined(HAVE_LONGLONG) */
7309 /****************************************************************************
7310 Get a lock offset, dealing with large offset requests.
7311 ****************************************************************************/
7313 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7314 bool large_file_format, bool *err)
7316 uint64_t offset = 0;
7320 if(!large_file_format) {
7321 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7324 #if defined(HAVE_LONGLONG)
7325 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7326 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7327 #else /* HAVE_LONGLONG */
7330 * NT4.x seems to be broken in that it sends large file (64 bit)
7331 * lockingX calls even if the CAP_LARGE_FILES was *not*
7332 * negotiated. For boxes without large unsigned ints mangle the
7333 * lock offset by mapping the top 32 bits onto the lower 32.
7336 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7337 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7338 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7341 if((new_low = map_lock_offset(high, low)) == 0) {
7343 return (uint64_t)-1;
7346 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7347 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7348 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7349 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7352 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7353 #endif /* HAVE_LONGLONG */
7359 NTSTATUS smbd_do_locking(struct smb_request *req,
7363 uint16_t num_ulocks,
7364 struct smbd_lock_element *ulocks,
7366 struct smbd_lock_element *locks,
7369 connection_struct *conn = req->conn;
7371 NTSTATUS status = NT_STATUS_OK;
7375 /* Data now points at the beginning of the list
7376 of smb_unlkrng structs */
7377 for(i = 0; i < (int)num_ulocks; i++) {
7378 struct smbd_lock_element *e = &ulocks[i];
7380 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7381 "pid %u, file %s\n",
7384 (unsigned int)e->smblctx,
7387 if (e->brltype != UNLOCK_LOCK) {
7388 /* this can only happen with SMB2 */
7389 return NT_STATUS_INVALID_PARAMETER;
7392 status = do_unlock(req->sconn->msg_ctx,
7399 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7400 nt_errstr(status)));
7402 if (!NT_STATUS_IS_OK(status)) {
7407 /* Setup the timeout in seconds. */
7409 if (!lp_blocking_locks(SNUM(conn))) {
7413 /* Data now points at the beginning of the list
7414 of smb_lkrng structs */
7416 for(i = 0; i < (int)num_locks; i++) {
7417 struct smbd_lock_element *e = &locks[i];
7419 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7420 "%llu, file %s timeout = %d\n",
7423 (unsigned long long)e->smblctx,
7427 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7428 struct blocking_lock_record *blr = NULL;
7430 if (num_locks > 1) {
7432 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7433 * if the lock vector contains one entry. When given mutliple cancel
7434 * requests in a single PDU we expect the server to return an
7435 * error. Windows servers seem to accept the request but only
7436 * cancel the first lock.
7437 * JRA - Do what Windows does (tm) :-).
7441 /* MS-CIFS (2.2.4.32.1) behavior. */
7442 return NT_STATUS_DOS(ERRDOS,
7443 ERRcancelviolation);
7445 /* Windows behavior. */
7447 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7448 "cancel request\n"));
7454 if (lp_blocking_locks(SNUM(conn))) {
7456 /* Schedule a message to ourselves to
7457 remove the blocking lock record and
7458 return the right error. */
7460 blr = blocking_lock_cancel_smb1(fsp,
7466 NT_STATUS_FILE_LOCK_CONFLICT);
7468 return NT_STATUS_DOS(
7470 ERRcancelviolation);
7473 /* Remove a matching pending lock. */
7474 status = do_lock_cancel(fsp,
7481 bool blocking_lock = timeout ? true : false;
7482 bool defer_lock = false;
7483 struct byte_range_lock *br_lck;
7484 uint64_t block_smblctx;
7486 br_lck = do_lock(req->sconn->msg_ctx,
7498 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7499 /* Windows internal resolution for blocking locks seems
7500 to be about 200ms... Don't wait for less than that. JRA. */
7501 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7502 timeout = lp_lock_spin_time();
7507 /* If a lock sent with timeout of zero would fail, and
7508 * this lock has been requested multiple times,
7509 * according to brl_lock_failed() we convert this
7510 * request to a blocking lock with a timeout of between
7511 * 150 - 300 milliseconds.
7513 * If lp_lock_spin_time() has been set to 0, we skip
7514 * this blocking retry and fail immediately.
7516 * Replacement for do_lock_spin(). JRA. */
7518 if (!req->sconn->using_smb2 &&
7519 br_lck && lp_blocking_locks(SNUM(conn)) &&
7520 lp_lock_spin_time() && !blocking_lock &&
7521 NT_STATUS_EQUAL((status),
7522 NT_STATUS_FILE_LOCK_CONFLICT))
7525 timeout = lp_lock_spin_time();
7528 if (br_lck && defer_lock) {
7530 * A blocking lock was requested. Package up
7531 * this smb into a queued request and push it
7532 * onto the blocking lock queue.
7534 if(push_blocking_lock_request(br_lck,
7545 TALLOC_FREE(br_lck);
7547 return NT_STATUS_OK;
7551 TALLOC_FREE(br_lck);
7554 if (!NT_STATUS_IS_OK(status)) {
7559 /* If any of the above locks failed, then we must unlock
7560 all of the previous locks (X/Open spec). */
7562 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7564 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7565 i = -1; /* we want to skip the for loop */
7569 * Ensure we don't do a remove on the lock that just failed,
7570 * as under POSIX rules, if we have a lock already there, we
7571 * will delete it (and we shouldn't) .....
7573 for(i--; i >= 0; i--) {
7574 struct smbd_lock_element *e = &locks[i];
7576 do_unlock(req->sconn->msg_ctx,
7586 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7587 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7589 return NT_STATUS_OK;
7592 /****************************************************************************
7593 Reply to a lockingX request.
7594 ****************************************************************************/
7596 void reply_lockingX(struct smb_request *req)
7598 connection_struct *conn = req->conn;
7600 unsigned char locktype;
7601 unsigned char oplocklevel;
7606 const uint8_t *data;
7607 bool large_file_format;
7609 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7610 struct smbd_lock_element *ulocks;
7611 struct smbd_lock_element *locks;
7614 START_PROFILE(SMBlockingX);
7617 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7618 END_PROFILE(SMBlockingX);
7622 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7623 locktype = CVAL(req->vwv+3, 0);
7624 oplocklevel = CVAL(req->vwv+3, 1);
7625 num_ulocks = SVAL(req->vwv+6, 0);
7626 num_locks = SVAL(req->vwv+7, 0);
7627 lock_timeout = IVAL(req->vwv+4, 0);
7628 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7630 if (!check_fsp(conn, req, fsp)) {
7631 END_PROFILE(SMBlockingX);
7637 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7638 /* we don't support these - and CANCEL_LOCK makes w2k
7639 and XP reboot so I don't really want to be
7640 compatible! (tridge) */
7641 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7642 END_PROFILE(SMBlockingX);
7646 /* Check if this is an oplock break on a file
7647 we have granted an oplock on.
7649 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7650 /* Client can insist on breaking to none. */
7651 bool break_to_none = (oplocklevel == 0);
7654 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7655 "for fnum = %d\n", (unsigned int)oplocklevel,
7659 * Make sure we have granted an exclusive or batch oplock on
7663 if (fsp->oplock_type == 0) {
7665 /* The Samba4 nbench simulator doesn't understand
7666 the difference between break to level2 and break
7667 to none from level2 - it sends oplock break
7668 replies in both cases. Don't keep logging an error
7669 message here - just ignore it. JRA. */
7671 DEBUG(5,("reply_lockingX: Error : oplock break from "
7672 "client for fnum = %d (oplock=%d) and no "
7673 "oplock granted on this file (%s).\n",
7674 fsp->fnum, fsp->oplock_type,
7677 /* if this is a pure oplock break request then don't
7679 if (num_locks == 0 && num_ulocks == 0) {
7680 END_PROFILE(SMBlockingX);
7683 END_PROFILE(SMBlockingX);
7684 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7689 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7691 result = remove_oplock(fsp);
7693 result = downgrade_oplock(fsp);
7697 DEBUG(0, ("reply_lockingX: error in removing "
7698 "oplock on file %s\n", fsp_str_dbg(fsp)));
7699 /* Hmmm. Is this panic justified? */
7700 smb_panic("internal tdb error");
7703 reply_to_oplock_break_requests(fsp);
7705 /* if this is a pure oplock break request then don't send a
7707 if (num_locks == 0 && num_ulocks == 0) {
7708 /* Sanity check - ensure a pure oplock break is not a
7710 if(CVAL(req->vwv+0, 0) != 0xff)
7711 DEBUG(0,("reply_lockingX: Error : pure oplock "
7712 "break is a chained %d request !\n",
7713 (unsigned int)CVAL(req->vwv+0, 0)));
7714 END_PROFILE(SMBlockingX);
7720 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7721 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7722 END_PROFILE(SMBlockingX);
7726 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7727 if (ulocks == NULL) {
7728 reply_nterror(req, NT_STATUS_NO_MEMORY);
7729 END_PROFILE(SMBlockingX);
7733 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7734 if (locks == NULL) {
7735 reply_nterror(req, NT_STATUS_NO_MEMORY);
7736 END_PROFILE(SMBlockingX);
7740 /* Data now points at the beginning of the list
7741 of smb_unlkrng structs */
7742 for(i = 0; i < (int)num_ulocks; i++) {
7743 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7744 ulocks[i].count = get_lock_count(data, i, large_file_format);
7745 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7746 ulocks[i].brltype = UNLOCK_LOCK;
7749 * There is no error code marked "stupid client bug".... :-).
7752 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7753 END_PROFILE(SMBlockingX);
7758 /* Now do any requested locks */
7759 data += ((large_file_format ? 20 : 10)*num_ulocks);
7761 /* Data now points at the beginning of the list
7762 of smb_lkrng structs */
7764 for(i = 0; i < (int)num_locks; i++) {
7765 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7766 locks[i].count = get_lock_count(data, i, large_file_format);
7767 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7769 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7770 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7771 locks[i].brltype = PENDING_READ_LOCK;
7773 locks[i].brltype = READ_LOCK;
7776 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7777 locks[i].brltype = PENDING_WRITE_LOCK;
7779 locks[i].brltype = WRITE_LOCK;
7784 * There is no error code marked "stupid client bug".... :-).
7787 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7788 END_PROFILE(SMBlockingX);
7793 status = smbd_do_locking(req, fsp,
7794 locktype, lock_timeout,
7798 if (!NT_STATUS_IS_OK(status)) {
7799 END_PROFILE(SMBlockingX);
7800 reply_nterror(req, status);
7804 END_PROFILE(SMBlockingX);
7808 reply_outbuf(req, 2, 0);
7810 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7811 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7813 END_PROFILE(SMBlockingX);
7818 #define DBGC_CLASS DBGC_ALL
7820 /****************************************************************************
7821 Reply to a SMBreadbmpx (read block multiplex) request.
7822 Always reply with an error, if someone has a platform really needs this,
7823 please contact vl@samba.org
7824 ****************************************************************************/
7826 void reply_readbmpx(struct smb_request *req)
7828 START_PROFILE(SMBreadBmpx);
7829 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7830 END_PROFILE(SMBreadBmpx);
7834 /****************************************************************************
7835 Reply to a SMBreadbs (read block multiplex secondary) request.
7836 Always reply with an error, if someone has a platform really needs this,
7837 please contact vl@samba.org
7838 ****************************************************************************/
7840 void reply_readbs(struct smb_request *req)
7842 START_PROFILE(SMBreadBs);
7843 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7844 END_PROFILE(SMBreadBs);
7848 /****************************************************************************
7849 Reply to a SMBsetattrE.
7850 ****************************************************************************/
7852 void reply_setattrE(struct smb_request *req)
7854 connection_struct *conn = req->conn;
7855 struct smb_file_time ft;
7859 START_PROFILE(SMBsetattrE);
7863 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7867 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7869 if(!fsp || (fsp->conn != conn)) {
7870 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7875 * Convert the DOS times into unix times.
7878 ft.atime = convert_time_t_to_timespec(
7879 srv_make_unix_date2(req->vwv+3));
7880 ft.mtime = convert_time_t_to_timespec(
7881 srv_make_unix_date2(req->vwv+5));
7882 ft.create_time = convert_time_t_to_timespec(
7883 srv_make_unix_date2(req->vwv+1));
7885 reply_outbuf(req, 0, 0);
7888 * Patch from Ray Frush <frush@engr.colostate.edu>
7889 * Sometimes times are sent as zero - ignore them.
7892 /* Ensure we have a valid stat struct for the source. */
7893 status = vfs_stat_fsp(fsp);
7894 if (!NT_STATUS_IS_OK(status)) {
7895 reply_nterror(req, status);
7899 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7900 if (!NT_STATUS_IS_OK(status)) {
7901 reply_nterror(req, status);
7905 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7908 (unsigned int)ft.atime.tv_sec,
7909 (unsigned int)ft.mtime.tv_sec,
7910 (unsigned int)ft.create_time.tv_sec
7913 END_PROFILE(SMBsetattrE);
7918 /* Back from the dead for OS/2..... JRA. */
7920 /****************************************************************************
7921 Reply to a SMBwritebmpx (write block multiplex primary) request.
7922 Always reply with an error, if someone has a platform really needs this,
7923 please contact vl@samba.org
7924 ****************************************************************************/
7926 void reply_writebmpx(struct smb_request *req)
7928 START_PROFILE(SMBwriteBmpx);
7929 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7930 END_PROFILE(SMBwriteBmpx);
7934 /****************************************************************************
7935 Reply to a SMBwritebs (write block multiplex secondary) request.
7936 Always reply with an error, if someone has a platform really needs this,
7937 please contact vl@samba.org
7938 ****************************************************************************/
7940 void reply_writebs(struct smb_request *req)
7942 START_PROFILE(SMBwriteBs);
7943 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7944 END_PROFILE(SMBwriteBs);
7948 /****************************************************************************
7949 Reply to a SMBgetattrE.
7950 ****************************************************************************/
7952 void reply_getattrE(struct smb_request *req)
7954 connection_struct *conn = req->conn;
7957 struct timespec create_ts;
7959 START_PROFILE(SMBgetattrE);
7962 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7963 END_PROFILE(SMBgetattrE);
7967 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7969 if(!fsp || (fsp->conn != conn)) {
7970 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7971 END_PROFILE(SMBgetattrE);
7975 /* Do an fstat on this file */
7977 reply_nterror(req, map_nt_error_from_unix(errno));
7978 END_PROFILE(SMBgetattrE);
7982 mode = dos_mode(conn, fsp->fsp_name);
7985 * Convert the times into dos times. Set create
7986 * date to be last modify date as UNIX doesn't save
7990 reply_outbuf(req, 11, 0);
7992 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7993 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7994 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7995 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7996 /* Should we check pending modtime here ? JRA */
7997 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7998 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8000 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8001 SIVAL(req->outbuf, smb_vwv6, 0);
8002 SIVAL(req->outbuf, smb_vwv8, 0);
8004 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8005 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8006 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8008 SSVAL(req->outbuf,smb_vwv10, mode);
8010 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
8012 END_PROFILE(SMBgetattrE);