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 0x81: /* 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,0x82);
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,SMBkeepalive);
621 case 0x82: /* positive session response */
622 case 0x83: /* negative session response */
623 case 0x84: /* retarget session response */
624 DEBUG(0,("Unexpected session response\n"));
627 case SMBkeepalive: /* 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 = CAN_WRITE(conn) ?
866 SIVAL(req->outbuf, smb_vwv3, perm1);
867 SIVAL(req->outbuf, smb_vwv5, perm2);
869 reply_outbuf(req, 3, 0);
872 if ((message_push_string(&req->outbuf, server_devicetype,
873 STR_TERMINATE|STR_ASCII) == -1)
874 || (message_push_string(&req->outbuf, fstype,
875 STR_TERMINATE) == -1)) {
876 reply_nterror(req, NT_STATUS_NO_MEMORY);
877 END_PROFILE(SMBtconX);
881 /* what does setting this bit do? It is set by NT4 and
882 may affect the ability to autorun mounted cdroms */
883 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
884 (lp_csc_policy(SNUM(conn)) << 2));
886 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
887 DEBUG(2,("Serving %s as a Dfs root\n",
888 lp_servicename(SNUM(conn)) ));
889 SSVAL(req->outbuf, smb_vwv2,
890 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
895 DEBUG(3,("tconX service=%s \n",
898 /* set the incoming and outgoing tid to the just created one */
899 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
900 SSVAL(req->outbuf,smb_tid,conn->cnum);
902 END_PROFILE(SMBtconX);
904 req->tid = conn->cnum;
909 /****************************************************************************
910 Reply to an unknown type.
911 ****************************************************************************/
913 void reply_unknown_new(struct smb_request *req, uint8 type)
915 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
916 smb_fn_name(type), type, type));
917 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
921 /****************************************************************************
923 conn POINTER CAN BE NULL HERE !
924 ****************************************************************************/
926 void reply_ioctl(struct smb_request *req)
928 connection_struct *conn = req->conn;
935 START_PROFILE(SMBioctl);
938 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
939 END_PROFILE(SMBioctl);
943 device = SVAL(req->vwv+1, 0);
944 function = SVAL(req->vwv+2, 0);
945 ioctl_code = (device << 16) + function;
947 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
949 switch (ioctl_code) {
950 case IOCTL_QUERY_JOB_INFO:
954 reply_force_doserror(req, ERRSRV, ERRnosupport);
955 END_PROFILE(SMBioctl);
959 reply_outbuf(req, 8, replysize+1);
960 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
961 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
962 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
963 p = smb_buf(req->outbuf);
964 memset(p, '\0', replysize+1); /* valgrind-safe. */
965 p += 1; /* Allow for alignment */
967 switch (ioctl_code) {
968 case IOCTL_QUERY_JOB_INFO:
970 files_struct *fsp = file_fsp(
971 req, SVAL(req->vwv+0, 0));
973 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
974 END_PROFILE(SMBioctl);
978 if (fsp->print_file) {
979 SSVAL(p, 0, fsp->print_file->rap_jobid);
983 srvstr_push((char *)req->outbuf, req->flags2, p+2,
984 lp_netbios_name(), 15,
985 STR_TERMINATE|STR_ASCII);
987 srvstr_push((char *)req->outbuf, req->flags2,
988 p+18, lp_servicename(SNUM(conn)),
989 13, STR_TERMINATE|STR_ASCII);
997 END_PROFILE(SMBioctl);
1001 /****************************************************************************
1002 Strange checkpath NTSTATUS mapping.
1003 ****************************************************************************/
1005 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1007 /* Strange DOS error code semantics only for checkpath... */
1008 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1009 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1010 /* We need to map to ERRbadpath */
1011 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1017 /****************************************************************************
1018 Reply to a checkpath.
1019 ****************************************************************************/
1021 void reply_checkpath(struct smb_request *req)
1023 connection_struct *conn = req->conn;
1024 struct smb_filename *smb_fname = NULL;
1027 TALLOC_CTX *ctx = talloc_tos();
1029 START_PROFILE(SMBcheckpath);
1031 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1032 STR_TERMINATE, &status);
1034 if (!NT_STATUS_IS_OK(status)) {
1035 status = map_checkpath_error(req->flags2, status);
1036 reply_nterror(req, status);
1037 END_PROFILE(SMBcheckpath);
1041 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1043 status = filename_convert(ctx,
1045 req->flags2 & FLAGS2_DFS_PATHNAMES,
1051 if (!NT_STATUS_IS_OK(status)) {
1052 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1053 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1054 ERRSRV, ERRbadpath);
1055 END_PROFILE(SMBcheckpath);
1061 if (!VALID_STAT(smb_fname->st) &&
1062 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1063 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1064 smb_fname_str_dbg(smb_fname), strerror(errno)));
1065 status = map_nt_error_from_unix(errno);
1069 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1070 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1071 ERRDOS, ERRbadpath);
1075 reply_outbuf(req, 0, 0);
1078 /* We special case this - as when a Windows machine
1079 is parsing a path is steps through the components
1080 one at a time - if a component fails it expects
1081 ERRbadpath, not ERRbadfile.
1083 status = map_checkpath_error(req->flags2, status);
1084 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1086 * Windows returns different error codes if
1087 * the parent directory is valid but not the
1088 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1089 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1090 * if the path is invalid.
1092 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1093 ERRDOS, ERRbadpath);
1097 reply_nterror(req, status);
1100 TALLOC_FREE(smb_fname);
1101 END_PROFILE(SMBcheckpath);
1105 /****************************************************************************
1107 ****************************************************************************/
1109 void reply_getatr(struct smb_request *req)
1111 connection_struct *conn = req->conn;
1112 struct smb_filename *smb_fname = NULL;
1119 TALLOC_CTX *ctx = talloc_tos();
1120 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1122 START_PROFILE(SMBgetatr);
1124 p = (const char *)req->buf + 1;
1125 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1126 if (!NT_STATUS_IS_OK(status)) {
1127 reply_nterror(req, status);
1131 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1132 under WfWg - weird! */
1133 if (*fname == '\0') {
1134 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1135 if (!CAN_WRITE(conn)) {
1136 mode |= FILE_ATTRIBUTE_READONLY;
1141 status = filename_convert(ctx,
1143 req->flags2 & FLAGS2_DFS_PATHNAMES,
1148 if (!NT_STATUS_IS_OK(status)) {
1149 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1150 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1151 ERRSRV, ERRbadpath);
1154 reply_nterror(req, status);
1157 if (!VALID_STAT(smb_fname->st) &&
1158 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1159 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1160 smb_fname_str_dbg(smb_fname),
1162 reply_nterror(req, map_nt_error_from_unix(errno));
1166 mode = dos_mode(conn, smb_fname);
1167 size = smb_fname->st.st_ex_size;
1169 if (ask_sharemode) {
1170 struct timespec write_time_ts;
1171 struct file_id fileid;
1173 ZERO_STRUCT(write_time_ts);
1174 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1175 get_file_infos(fileid, 0, NULL, &write_time_ts);
1176 if (!null_timespec(write_time_ts)) {
1177 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1181 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1182 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1187 reply_outbuf(req, 10, 0);
1189 SSVAL(req->outbuf,smb_vwv0,mode);
1190 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1191 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1193 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1195 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1197 if (get_Protocol() >= PROTOCOL_NT1) {
1198 SSVAL(req->outbuf, smb_flg2,
1199 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1202 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1203 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1206 TALLOC_FREE(smb_fname);
1208 END_PROFILE(SMBgetatr);
1212 /****************************************************************************
1214 ****************************************************************************/
1216 void reply_setatr(struct smb_request *req)
1218 struct smb_file_time ft;
1219 connection_struct *conn = req->conn;
1220 struct smb_filename *smb_fname = NULL;
1226 TALLOC_CTX *ctx = talloc_tos();
1228 START_PROFILE(SMBsetatr);
1233 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1237 p = (const char *)req->buf + 1;
1238 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1239 if (!NT_STATUS_IS_OK(status)) {
1240 reply_nterror(req, status);
1244 status = filename_convert(ctx,
1246 req->flags2 & FLAGS2_DFS_PATHNAMES,
1251 if (!NT_STATUS_IS_OK(status)) {
1252 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1253 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1254 ERRSRV, ERRbadpath);
1257 reply_nterror(req, status);
1261 if (smb_fname->base_name[0] == '.' &&
1262 smb_fname->base_name[1] == '\0') {
1264 * Not sure here is the right place to catch this
1265 * condition. Might be moved to somewhere else later -- vl
1267 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1271 mode = SVAL(req->vwv+0, 0);
1272 mtime = srv_make_unix_date3(req->vwv+1);
1274 ft.mtime = convert_time_t_to_timespec(mtime);
1275 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1276 if (!NT_STATUS_IS_OK(status)) {
1277 reply_nterror(req, status);
1281 if (mode != FILE_ATTRIBUTE_NORMAL) {
1282 if (VALID_STAT_OF_DIR(smb_fname->st))
1283 mode |= FILE_ATTRIBUTE_DIRECTORY;
1285 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1287 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1289 reply_nterror(req, map_nt_error_from_unix(errno));
1294 reply_outbuf(req, 0, 0);
1296 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1299 TALLOC_FREE(smb_fname);
1300 END_PROFILE(SMBsetatr);
1304 /****************************************************************************
1306 ****************************************************************************/
1308 void reply_dskattr(struct smb_request *req)
1310 connection_struct *conn = req->conn;
1311 uint64_t dfree,dsize,bsize;
1312 START_PROFILE(SMBdskattr);
1314 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1315 reply_nterror(req, map_nt_error_from_unix(errno));
1316 END_PROFILE(SMBdskattr);
1320 reply_outbuf(req, 5, 0);
1322 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1323 double total_space, free_space;
1324 /* we need to scale this to a number that DOS6 can handle. We
1325 use floating point so we can handle large drives on systems
1326 that don't have 64 bit integers
1328 we end up displaying a maximum of 2G to DOS systems
1330 total_space = dsize * (double)bsize;
1331 free_space = dfree * (double)bsize;
1333 dsize = (uint64_t)((total_space+63*512) / (64*512));
1334 dfree = (uint64_t)((free_space+63*512) / (64*512));
1336 if (dsize > 0xFFFF) dsize = 0xFFFF;
1337 if (dfree > 0xFFFF) dfree = 0xFFFF;
1339 SSVAL(req->outbuf,smb_vwv0,dsize);
1340 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1341 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1342 SSVAL(req->outbuf,smb_vwv3,dfree);
1344 SSVAL(req->outbuf,smb_vwv0,dsize);
1345 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1346 SSVAL(req->outbuf,smb_vwv2,512);
1347 SSVAL(req->outbuf,smb_vwv3,dfree);
1350 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1352 END_PROFILE(SMBdskattr);
1357 * Utility function to split the filename from the directory.
1359 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1360 char **fname_dir_out,
1361 char **fname_mask_out)
1363 const char *p = NULL;
1364 char *fname_dir = NULL;
1365 char *fname_mask = NULL;
1367 p = strrchr_m(fname_in, '/');
1369 fname_dir = talloc_strdup(ctx, ".");
1370 fname_mask = talloc_strdup(ctx, fname_in);
1372 fname_dir = talloc_strndup(ctx, fname_in,
1373 PTR_DIFF(p, fname_in));
1374 fname_mask = talloc_strdup(ctx, p+1);
1377 if (!fname_dir || !fname_mask) {
1378 TALLOC_FREE(fname_dir);
1379 TALLOC_FREE(fname_mask);
1380 return NT_STATUS_NO_MEMORY;
1383 *fname_dir_out = fname_dir;
1384 *fname_mask_out = fname_mask;
1385 return NT_STATUS_OK;
1388 /****************************************************************************
1390 Can be called from SMBsearch, SMBffirst or SMBfunique.
1391 ****************************************************************************/
1393 void reply_search(struct smb_request *req)
1395 connection_struct *conn = req->conn;
1397 const char *mask = NULL;
1398 char *directory = NULL;
1399 struct smb_filename *smb_fname = NULL;
1403 struct timespec date;
1405 unsigned int numentries = 0;
1406 unsigned int maxentries = 0;
1407 bool finished = False;
1412 bool check_descend = False;
1413 bool expect_close = False;
1415 bool mask_contains_wcard = False;
1416 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1417 TALLOC_CTX *ctx = talloc_tos();
1418 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1419 struct dptr_struct *dirptr = NULL;
1420 struct smbd_server_connection *sconn = req->sconn;
1422 START_PROFILE(SMBsearch);
1425 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1429 if (lp_posix_pathnames()) {
1430 reply_unknown_new(req, req->cmd);
1434 /* If we were called as SMBffirst then we must expect close. */
1435 if(req->cmd == SMBffirst) {
1436 expect_close = True;
1439 reply_outbuf(req, 1, 3);
1440 maxentries = SVAL(req->vwv+0, 0);
1441 dirtype = SVAL(req->vwv+1, 0);
1442 p = (const char *)req->buf + 1;
1443 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1444 &nt_status, &mask_contains_wcard);
1445 if (!NT_STATUS_IS_OK(nt_status)) {
1446 reply_nterror(req, nt_status);
1451 status_len = SVAL(p, 0);
1454 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1456 if (status_len == 0) {
1457 nt_status = filename_convert(ctx, conn,
1458 req->flags2 & FLAGS2_DFS_PATHNAMES,
1460 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1461 &mask_contains_wcard,
1463 if (!NT_STATUS_IS_OK(nt_status)) {
1464 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1465 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1466 ERRSRV, ERRbadpath);
1469 reply_nterror(req, nt_status);
1473 directory = smb_fname->base_name;
1475 p = strrchr_m(directory,'/');
1476 if ((p != NULL) && (*directory != '/')) {
1478 directory = talloc_strndup(ctx, directory,
1479 PTR_DIFF(p, directory));
1482 directory = talloc_strdup(ctx,".");
1486 reply_nterror(req, NT_STATUS_NO_MEMORY);
1490 memset((char *)status,'\0',21);
1491 SCVAL(status,0,(dirtype & 0x1F));
1493 nt_status = dptr_create(conn,
1500 mask_contains_wcard,
1503 if (!NT_STATUS_IS_OK(nt_status)) {
1504 reply_nterror(req, nt_status);
1507 dptr_num = dptr_dnum(dirptr);
1510 const char *dirpath;
1512 memcpy(status,p,21);
1513 status_dirtype = CVAL(status,0) & 0x1F;
1514 if (status_dirtype != (dirtype & 0x1F)) {
1515 dirtype = status_dirtype;
1518 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1522 dirpath = dptr_path(sconn, dptr_num);
1523 directory = talloc_strdup(ctx, dirpath);
1525 reply_nterror(req, NT_STATUS_NO_MEMORY);
1529 mask = dptr_wcard(sconn, dptr_num);
1534 * For a 'continue' search we have no string. So
1535 * check from the initial saved string.
1537 mask_contains_wcard = ms_has_wild(mask);
1538 dirtype = dptr_attr(sconn, dptr_num);
1541 DEBUG(4,("dptr_num is %d\n",dptr_num));
1543 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1544 dptr_init_search_op(dirptr);
1546 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1547 char buf[DIR_STRUCT_SIZE];
1548 memcpy(buf,status,21);
1549 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1550 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1551 reply_nterror(req, NT_STATUS_NO_MEMORY);
1554 dptr_fill(sconn, buf+12,dptr_num);
1555 if (dptr_zero(buf+12) && (status_len==0)) {
1560 if (message_push_blob(&req->outbuf,
1561 data_blob_const(buf, sizeof(buf)))
1563 reply_nterror(req, NT_STATUS_NO_MEMORY);
1571 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1574 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1575 directory,lp_dontdescend(SNUM(conn))));
1576 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1577 check_descend = True;
1580 for (i=numentries;(i<maxentries) && !finished;i++) {
1581 finished = !get_dir_entry(ctx,
1592 char buf[DIR_STRUCT_SIZE];
1593 memcpy(buf,status,21);
1594 if (!make_dir_struct(ctx,
1600 convert_timespec_to_time_t(date),
1601 !allow_long_path_components)) {
1602 reply_nterror(req, NT_STATUS_NO_MEMORY);
1605 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1608 if (message_push_blob(&req->outbuf,
1609 data_blob_const(buf, sizeof(buf)))
1611 reply_nterror(req, NT_STATUS_NO_MEMORY);
1621 /* If we were called as SMBffirst with smb_search_id == NULL
1622 and no entries were found then return error and close dirptr
1625 if (numentries == 0) {
1626 dptr_close(sconn, &dptr_num);
1627 } else if(expect_close && status_len == 0) {
1628 /* Close the dptr - we know it's gone */
1629 dptr_close(sconn, &dptr_num);
1632 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1633 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1634 dptr_close(sconn, &dptr_num);
1637 if ((numentries == 0) && !mask_contains_wcard) {
1638 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1642 SSVAL(req->outbuf,smb_vwv0,numentries);
1643 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1644 SCVAL(smb_buf(req->outbuf),0,5);
1645 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1647 /* The replies here are never long name. */
1648 SSVAL(req->outbuf, smb_flg2,
1649 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1650 if (!allow_long_path_components) {
1651 SSVAL(req->outbuf, smb_flg2,
1652 SVAL(req->outbuf, smb_flg2)
1653 & (~FLAGS2_LONG_PATH_COMPONENTS));
1656 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1657 SSVAL(req->outbuf, smb_flg2,
1658 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1660 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1661 smb_fn_name(req->cmd),
1668 TALLOC_FREE(directory);
1669 TALLOC_FREE(smb_fname);
1670 END_PROFILE(SMBsearch);
1674 /****************************************************************************
1675 Reply to a fclose (stop directory search).
1676 ****************************************************************************/
1678 void reply_fclose(struct smb_request *req)
1686 bool path_contains_wcard = False;
1687 TALLOC_CTX *ctx = talloc_tos();
1688 struct smbd_server_connection *sconn = req->sconn;
1690 START_PROFILE(SMBfclose);
1692 if (lp_posix_pathnames()) {
1693 reply_unknown_new(req, req->cmd);
1694 END_PROFILE(SMBfclose);
1698 p = (const char *)req->buf + 1;
1699 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1700 &err, &path_contains_wcard);
1701 if (!NT_STATUS_IS_OK(err)) {
1702 reply_nterror(req, err);
1703 END_PROFILE(SMBfclose);
1707 status_len = SVAL(p,0);
1710 if (status_len == 0) {
1711 reply_force_doserror(req, ERRSRV, ERRsrverror);
1712 END_PROFILE(SMBfclose);
1716 memcpy(status,p,21);
1718 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1719 /* Close the dptr - we know it's gone */
1720 dptr_close(sconn, &dptr_num);
1723 reply_outbuf(req, 1, 0);
1724 SSVAL(req->outbuf,smb_vwv0,0);
1726 DEBUG(3,("search close\n"));
1728 END_PROFILE(SMBfclose);
1732 /****************************************************************************
1734 ****************************************************************************/
1736 void reply_open(struct smb_request *req)
1738 connection_struct *conn = req->conn;
1739 struct smb_filename *smb_fname = NULL;
1751 uint32 create_disposition;
1752 uint32 create_options = 0;
1753 uint32_t private_flags = 0;
1755 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1756 TALLOC_CTX *ctx = talloc_tos();
1758 START_PROFILE(SMBopen);
1761 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1765 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1766 deny_mode = SVAL(req->vwv+0, 0);
1767 dos_attr = SVAL(req->vwv+1, 0);
1769 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1770 STR_TERMINATE, &status);
1771 if (!NT_STATUS_IS_OK(status)) {
1772 reply_nterror(req, status);
1776 status = filename_convert(ctx,
1778 req->flags2 & FLAGS2_DFS_PATHNAMES,
1783 if (!NT_STATUS_IS_OK(status)) {
1784 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1785 reply_botherror(req,
1786 NT_STATUS_PATH_NOT_COVERED,
1787 ERRSRV, ERRbadpath);
1790 reply_nterror(req, status);
1794 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1795 OPENX_FILE_EXISTS_OPEN, &access_mask,
1796 &share_mode, &create_disposition,
1797 &create_options, &private_flags)) {
1798 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1802 status = SMB_VFS_CREATE_FILE(
1805 0, /* root_dir_fid */
1806 smb_fname, /* fname */
1807 access_mask, /* access_mask */
1808 share_mode, /* share_access */
1809 create_disposition, /* create_disposition*/
1810 create_options, /* create_options */
1811 dos_attr, /* file_attributes */
1812 oplock_request, /* oplock_request */
1813 0, /* allocation_size */
1820 if (!NT_STATUS_IS_OK(status)) {
1821 if (open_was_deferred(req->mid)) {
1822 /* We have re-scheduled this call. */
1825 reply_openerror(req, status);
1829 size = smb_fname->st.st_ex_size;
1830 fattr = dos_mode(conn, smb_fname);
1832 /* Deal with other possible opens having a modified
1834 if (ask_sharemode) {
1835 struct timespec write_time_ts;
1837 ZERO_STRUCT(write_time_ts);
1838 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1839 if (!null_timespec(write_time_ts)) {
1840 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1844 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1846 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1847 DEBUG(3,("attempt to open a directory %s\n",
1849 close_file(req, fsp, ERROR_CLOSE);
1850 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1851 ERRDOS, ERRnoaccess);
1855 reply_outbuf(req, 7, 0);
1856 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1857 SSVAL(req->outbuf,smb_vwv1,fattr);
1858 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1859 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1861 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1863 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1864 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1866 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1867 SCVAL(req->outbuf,smb_flg,
1868 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1871 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1872 SCVAL(req->outbuf,smb_flg,
1873 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1876 TALLOC_FREE(smb_fname);
1877 END_PROFILE(SMBopen);
1881 /****************************************************************************
1882 Reply to an open and X.
1883 ****************************************************************************/
1885 void reply_open_and_X(struct smb_request *req)
1887 connection_struct *conn = req->conn;
1888 struct smb_filename *smb_fname = NULL;
1893 /* Breakout the oplock request bits so we can set the
1894 reply bits separately. */
1895 int ex_oplock_request;
1896 int core_oplock_request;
1899 int smb_sattr = SVAL(req->vwv+4, 0);
1900 uint32 smb_time = make_unix_date3(req->vwv+6);
1908 uint64_t allocation_size;
1909 ssize_t retval = -1;
1912 uint32 create_disposition;
1913 uint32 create_options = 0;
1914 uint32_t private_flags = 0;
1915 TALLOC_CTX *ctx = talloc_tos();
1917 START_PROFILE(SMBopenX);
1919 if (req->wct < 15) {
1920 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1924 open_flags = SVAL(req->vwv+2, 0);
1925 deny_mode = SVAL(req->vwv+3, 0);
1926 smb_attr = SVAL(req->vwv+5, 0);
1927 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1928 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1929 oplock_request = ex_oplock_request | core_oplock_request;
1930 smb_ofun = SVAL(req->vwv+8, 0);
1931 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1933 /* If it's an IPC, pass off the pipe handler. */
1935 if (lp_nt_pipe_support()) {
1936 reply_open_pipe_and_X(conn, req);
1938 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1943 /* XXXX we need to handle passed times, sattr and flags */
1944 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1945 STR_TERMINATE, &status);
1946 if (!NT_STATUS_IS_OK(status)) {
1947 reply_nterror(req, status);
1951 status = filename_convert(ctx,
1953 req->flags2 & FLAGS2_DFS_PATHNAMES,
1958 if (!NT_STATUS_IS_OK(status)) {
1959 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1960 reply_botherror(req,
1961 NT_STATUS_PATH_NOT_COVERED,
1962 ERRSRV, ERRbadpath);
1965 reply_nterror(req, status);
1969 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1970 &access_mask, &share_mode,
1971 &create_disposition,
1974 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1978 status = SMB_VFS_CREATE_FILE(
1981 0, /* root_dir_fid */
1982 smb_fname, /* fname */
1983 access_mask, /* access_mask */
1984 share_mode, /* share_access */
1985 create_disposition, /* create_disposition*/
1986 create_options, /* create_options */
1987 smb_attr, /* file_attributes */
1988 oplock_request, /* oplock_request */
1989 0, /* allocation_size */
1994 &smb_action); /* pinfo */
1996 if (!NT_STATUS_IS_OK(status)) {
1997 if (open_was_deferred(req->mid)) {
1998 /* We have re-scheduled this call. */
2001 reply_openerror(req, status);
2005 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2006 if the file is truncated or created. */
2007 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2008 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2009 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2010 close_file(req, fsp, ERROR_CLOSE);
2011 reply_nterror(req, NT_STATUS_DISK_FULL);
2014 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
2016 close_file(req, fsp, ERROR_CLOSE);
2017 reply_nterror(req, NT_STATUS_DISK_FULL);
2020 status = vfs_stat_fsp(fsp);
2021 if (!NT_STATUS_IS_OK(status)) {
2022 close_file(req, fsp, ERROR_CLOSE);
2023 reply_nterror(req, status);
2028 fattr = dos_mode(conn, fsp->fsp_name);
2029 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2030 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2031 close_file(req, fsp, ERROR_CLOSE);
2032 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2036 /* If the caller set the extended oplock request bit
2037 and we granted one (by whatever means) - set the
2038 correct bit for extended oplock reply.
2041 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2042 smb_action |= EXTENDED_OPLOCK_GRANTED;
2045 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2046 smb_action |= EXTENDED_OPLOCK_GRANTED;
2049 /* If the caller set the core oplock request bit
2050 and we granted one (by whatever means) - set the
2051 correct bit for core oplock reply.
2054 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2055 reply_outbuf(req, 19, 0);
2057 reply_outbuf(req, 15, 0);
2060 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2061 SCVAL(req->outbuf, smb_flg,
2062 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2065 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2066 SCVAL(req->outbuf, smb_flg,
2067 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2070 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2071 SSVAL(req->outbuf,smb_vwv3,fattr);
2072 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2073 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2075 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2077 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2078 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2079 SSVAL(req->outbuf,smb_vwv11,smb_action);
2081 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2082 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2087 TALLOC_FREE(smb_fname);
2088 END_PROFILE(SMBopenX);
2092 /****************************************************************************
2093 Reply to a SMBulogoffX.
2094 ****************************************************************************/
2096 void reply_ulogoffX(struct smb_request *req)
2098 struct smbd_server_connection *sconn = req->sconn;
2101 START_PROFILE(SMBulogoffX);
2103 vuser = get_valid_user_struct(sconn, req->vuid);
2106 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2110 /* in user level security we are supposed to close any files
2111 open by this user */
2112 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2113 file_close_user(sconn, req->vuid);
2116 invalidate_vuid(sconn, req->vuid);
2118 reply_outbuf(req, 2, 0);
2120 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2122 END_PROFILE(SMBulogoffX);
2123 req->vuid = UID_FIELD_INVALID;
2127 /****************************************************************************
2128 Reply to a mknew or a create.
2129 ****************************************************************************/
2131 void reply_mknew(struct smb_request *req)
2133 connection_struct *conn = req->conn;
2134 struct smb_filename *smb_fname = NULL;
2137 struct smb_file_time ft;
2139 int oplock_request = 0;
2141 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2142 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2143 uint32 create_disposition;
2144 uint32 create_options = 0;
2145 TALLOC_CTX *ctx = talloc_tos();
2147 START_PROFILE(SMBcreate);
2151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2155 fattr = SVAL(req->vwv+0, 0);
2156 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2159 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2161 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2162 STR_TERMINATE, &status);
2163 if (!NT_STATUS_IS_OK(status)) {
2164 reply_nterror(req, status);
2168 status = filename_convert(ctx,
2170 req->flags2 & FLAGS2_DFS_PATHNAMES,
2175 if (!NT_STATUS_IS_OK(status)) {
2176 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2177 reply_botherror(req,
2178 NT_STATUS_PATH_NOT_COVERED,
2179 ERRSRV, ERRbadpath);
2182 reply_nterror(req, status);
2186 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2187 DEBUG(0,("Attempt to create file (%s) with volid set - "
2188 "please report this\n",
2189 smb_fname_str_dbg(smb_fname)));
2192 if(req->cmd == SMBmknew) {
2193 /* We should fail if file exists. */
2194 create_disposition = FILE_CREATE;
2196 /* Create if file doesn't exist, truncate if it does. */
2197 create_disposition = FILE_OVERWRITE_IF;
2200 status = SMB_VFS_CREATE_FILE(
2203 0, /* root_dir_fid */
2204 smb_fname, /* fname */
2205 access_mask, /* access_mask */
2206 share_mode, /* share_access */
2207 create_disposition, /* create_disposition*/
2208 create_options, /* create_options */
2209 fattr, /* file_attributes */
2210 oplock_request, /* oplock_request */
2211 0, /* allocation_size */
2212 0, /* private_flags */
2218 if (!NT_STATUS_IS_OK(status)) {
2219 if (open_was_deferred(req->mid)) {
2220 /* We have re-scheduled this call. */
2223 reply_openerror(req, status);
2227 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2228 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2229 if (!NT_STATUS_IS_OK(status)) {
2230 END_PROFILE(SMBcreate);
2234 reply_outbuf(req, 1, 0);
2235 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2237 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2238 SCVAL(req->outbuf,smb_flg,
2239 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2242 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2243 SCVAL(req->outbuf,smb_flg,
2244 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2247 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2248 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2249 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2250 (unsigned int)fattr));
2253 TALLOC_FREE(smb_fname);
2254 END_PROFILE(SMBcreate);
2258 /****************************************************************************
2259 Reply to a create temporary file.
2260 ****************************************************************************/
2262 void reply_ctemp(struct smb_request *req)
2264 connection_struct *conn = req->conn;
2265 struct smb_filename *smb_fname = NULL;
2273 TALLOC_CTX *ctx = talloc_tos();
2275 START_PROFILE(SMBctemp);
2278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2282 fattr = SVAL(req->vwv+0, 0);
2283 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2285 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2286 STR_TERMINATE, &status);
2287 if (!NT_STATUS_IS_OK(status)) {
2288 reply_nterror(req, status);
2292 fname = talloc_asprintf(ctx,
2296 fname = talloc_strdup(ctx, "TMXXXXXX");
2300 reply_nterror(req, NT_STATUS_NO_MEMORY);
2304 status = filename_convert(ctx, conn,
2305 req->flags2 & FLAGS2_DFS_PATHNAMES,
2310 if (!NT_STATUS_IS_OK(status)) {
2311 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2312 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2313 ERRSRV, ERRbadpath);
2316 reply_nterror(req, status);
2320 tmpfd = mkstemp(smb_fname->base_name);
2322 reply_nterror(req, map_nt_error_from_unix(errno));
2326 SMB_VFS_STAT(conn, smb_fname);
2328 /* We should fail if file does not exist. */
2329 status = SMB_VFS_CREATE_FILE(
2332 0, /* root_dir_fid */
2333 smb_fname, /* fname */
2334 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2335 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2336 FILE_OPEN, /* create_disposition*/
2337 0, /* create_options */
2338 fattr, /* file_attributes */
2339 oplock_request, /* oplock_request */
2340 0, /* allocation_size */
2341 0, /* private_flags */
2347 /* close fd from mkstemp() */
2350 if (!NT_STATUS_IS_OK(status)) {
2351 if (open_was_deferred(req->mid)) {
2352 /* We have re-scheduled this call. */
2355 reply_openerror(req, status);
2359 reply_outbuf(req, 1, 0);
2360 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2362 /* the returned filename is relative to the directory */
2363 s = strrchr_m(fsp->fsp_name->base_name, '/');
2365 s = fsp->fsp_name->base_name;
2371 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2372 thing in the byte section. JRA */
2373 SSVALS(p, 0, -1); /* what is this? not in spec */
2375 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2377 reply_nterror(req, NT_STATUS_NO_MEMORY);
2381 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2382 SCVAL(req->outbuf, smb_flg,
2383 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2386 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2387 SCVAL(req->outbuf, smb_flg,
2388 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2391 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2392 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2393 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2395 TALLOC_FREE(smb_fname);
2396 END_PROFILE(SMBctemp);
2400 /*******************************************************************
2401 Check if a user is allowed to rename a file.
2402 ********************************************************************/
2404 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2407 if (!CAN_WRITE(conn)) {
2408 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2411 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2412 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2413 /* Only bother to read the DOS attribute if we might deny the
2414 rename on the grounds of attribute missmatch. */
2415 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2416 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2417 return NT_STATUS_NO_SUCH_FILE;
2421 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2422 if (fsp->posix_open) {
2423 return NT_STATUS_OK;
2426 /* If no pathnames are open below this
2427 directory, allow the rename. */
2429 if (file_find_subpath(fsp)) {
2430 return NT_STATUS_ACCESS_DENIED;
2432 return NT_STATUS_OK;
2435 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2436 return NT_STATUS_OK;
2439 return NT_STATUS_ACCESS_DENIED;
2442 /*******************************************************************
2443 * unlink a file with all relevant access checks
2444 *******************************************************************/
2446 static NTSTATUS do_unlink(connection_struct *conn,
2447 struct smb_request *req,
2448 struct smb_filename *smb_fname,
2453 uint32 dirtype_orig = dirtype;
2456 bool posix_paths = lp_posix_pathnames();
2458 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2459 smb_fname_str_dbg(smb_fname),
2462 if (!CAN_WRITE(conn)) {
2463 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2467 ret = SMB_VFS_LSTAT(conn, smb_fname);
2469 ret = SMB_VFS_STAT(conn, smb_fname);
2472 return map_nt_error_from_unix(errno);
2475 fattr = dos_mode(conn, smb_fname);
2477 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2478 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2481 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2483 return NT_STATUS_NO_SUCH_FILE;
2486 if (!dir_check_ftype(conn, fattr, dirtype)) {
2487 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2488 return NT_STATUS_FILE_IS_A_DIRECTORY;
2490 return NT_STATUS_NO_SUCH_FILE;
2493 if (dirtype_orig & 0x8000) {
2494 /* These will never be set for POSIX. */
2495 return NT_STATUS_NO_SUCH_FILE;
2499 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2500 return NT_STATUS_FILE_IS_A_DIRECTORY;
2503 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2504 return NT_STATUS_NO_SUCH_FILE;
2507 if (dirtype & 0xFF00) {
2508 /* These will never be set for POSIX. */
2509 return NT_STATUS_NO_SUCH_FILE;
2514 return NT_STATUS_NO_SUCH_FILE;
2517 /* Can't delete a directory. */
2518 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2519 return NT_STATUS_FILE_IS_A_DIRECTORY;
2524 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2525 return NT_STATUS_OBJECT_NAME_INVALID;
2526 #endif /* JRATEST */
2528 /* On open checks the open itself will check the share mode, so
2529 don't do it here as we'll get it wrong. */
2531 status = SMB_VFS_CREATE_FILE
2534 0, /* root_dir_fid */
2535 smb_fname, /* fname */
2536 DELETE_ACCESS, /* access_mask */
2537 FILE_SHARE_NONE, /* share_access */
2538 FILE_OPEN, /* create_disposition*/
2539 FILE_NON_DIRECTORY_FILE, /* create_options */
2540 /* file_attributes */
2541 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2542 FILE_ATTRIBUTE_NORMAL,
2543 0, /* oplock_request */
2544 0, /* allocation_size */
2545 0, /* private_flags */
2551 if (!NT_STATUS_IS_OK(status)) {
2552 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2553 nt_errstr(status)));
2557 status = can_set_delete_on_close(fsp, fattr);
2558 if (!NT_STATUS_IS_OK(status)) {
2559 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2561 smb_fname_str_dbg(smb_fname),
2562 nt_errstr(status)));
2563 close_file(req, fsp, NORMAL_CLOSE);
2567 /* The set is across all open files on this dev/inode pair. */
2568 if (!set_delete_on_close(fsp, True, &conn->session_info->utok)) {
2569 close_file(req, fsp, NORMAL_CLOSE);
2570 return NT_STATUS_ACCESS_DENIED;
2573 return close_file(req, fsp, NORMAL_CLOSE);
2576 /****************************************************************************
2577 The guts of the unlink command, split out so it may be called by the NT SMB
2579 ****************************************************************************/
2581 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2582 uint32 dirtype, struct smb_filename *smb_fname,
2585 char *fname_dir = NULL;
2586 char *fname_mask = NULL;
2588 NTSTATUS status = NT_STATUS_OK;
2589 TALLOC_CTX *ctx = talloc_tos();
2591 /* Split up the directory from the filename/mask. */
2592 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2593 &fname_dir, &fname_mask);
2594 if (!NT_STATUS_IS_OK(status)) {
2599 * We should only check the mangled cache
2600 * here if unix_convert failed. This means
2601 * that the path in 'mask' doesn't exist
2602 * on the file system and so we need to look
2603 * for a possible mangle. This patch from
2604 * Tine Smukavec <valentin.smukavec@hermes.si>.
2607 if (!VALID_STAT(smb_fname->st) &&
2608 mangle_is_mangled(fname_mask, conn->params)) {
2609 char *new_mask = NULL;
2610 mangle_lookup_name_from_8_3(ctx, fname_mask,
2611 &new_mask, conn->params);
2613 TALLOC_FREE(fname_mask);
2614 fname_mask = new_mask;
2621 * Only one file needs to be unlinked. Append the mask back
2622 * onto the directory.
2624 TALLOC_FREE(smb_fname->base_name);
2625 if (ISDOT(fname_dir)) {
2626 /* Ensure we use canonical names on open. */
2627 smb_fname->base_name = talloc_asprintf(smb_fname,
2631 smb_fname->base_name = talloc_asprintf(smb_fname,
2636 if (!smb_fname->base_name) {
2637 status = NT_STATUS_NO_MEMORY;
2641 dirtype = FILE_ATTRIBUTE_NORMAL;
2644 status = check_name(conn, smb_fname->base_name);
2645 if (!NT_STATUS_IS_OK(status)) {
2649 status = do_unlink(conn, req, smb_fname, dirtype);
2650 if (!NT_STATUS_IS_OK(status)) {
2656 struct smb_Dir *dir_hnd = NULL;
2658 const char *dname = NULL;
2659 char *talloced = NULL;
2661 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2662 status = NT_STATUS_OBJECT_NAME_INVALID;
2666 if (strequal(fname_mask,"????????.???")) {
2667 TALLOC_FREE(fname_mask);
2668 fname_mask = talloc_strdup(ctx, "*");
2670 status = NT_STATUS_NO_MEMORY;
2675 status = check_name(conn, fname_dir);
2676 if (!NT_STATUS_IS_OK(status)) {
2680 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2682 if (dir_hnd == NULL) {
2683 status = map_nt_error_from_unix(errno);
2687 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2688 the pattern matches against the long name, otherwise the short name
2689 We don't implement this yet XXXX
2692 status = NT_STATUS_NO_SUCH_FILE;
2694 while ((dname = ReadDirName(dir_hnd, &offset,
2695 &smb_fname->st, &talloced))) {
2696 TALLOC_CTX *frame = talloc_stackframe();
2698 if (!is_visible_file(conn, fname_dir, dname,
2699 &smb_fname->st, true)) {
2701 TALLOC_FREE(talloced);
2705 /* Quick check for "." and ".." */
2706 if (ISDOT(dname) || ISDOTDOT(dname)) {
2708 TALLOC_FREE(talloced);
2712 if(!mask_match(dname, fname_mask,
2713 conn->case_sensitive)) {
2715 TALLOC_FREE(talloced);
2719 TALLOC_FREE(smb_fname->base_name);
2720 if (ISDOT(fname_dir)) {
2721 /* Ensure we use canonical names on open. */
2722 smb_fname->base_name =
2723 talloc_asprintf(smb_fname, "%s",
2726 smb_fname->base_name =
2727 talloc_asprintf(smb_fname, "%s/%s",
2731 if (!smb_fname->base_name) {
2732 TALLOC_FREE(dir_hnd);
2733 status = NT_STATUS_NO_MEMORY;
2735 TALLOC_FREE(talloced);
2739 status = check_name(conn, smb_fname->base_name);
2740 if (!NT_STATUS_IS_OK(status)) {
2741 TALLOC_FREE(dir_hnd);
2743 TALLOC_FREE(talloced);
2747 status = do_unlink(conn, req, smb_fname, dirtype);
2748 if (!NT_STATUS_IS_OK(status)) {
2750 TALLOC_FREE(talloced);
2755 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2756 smb_fname->base_name));
2759 TALLOC_FREE(talloced);
2761 TALLOC_FREE(dir_hnd);
2764 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2765 status = map_nt_error_from_unix(errno);
2769 TALLOC_FREE(fname_dir);
2770 TALLOC_FREE(fname_mask);
2774 /****************************************************************************
2776 ****************************************************************************/
2778 void reply_unlink(struct smb_request *req)
2780 connection_struct *conn = req->conn;
2782 struct smb_filename *smb_fname = NULL;
2785 bool path_contains_wcard = False;
2786 TALLOC_CTX *ctx = talloc_tos();
2788 START_PROFILE(SMBunlink);
2791 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2795 dirtype = SVAL(req->vwv+0, 0);
2797 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2798 STR_TERMINATE, &status,
2799 &path_contains_wcard);
2800 if (!NT_STATUS_IS_OK(status)) {
2801 reply_nterror(req, status);
2805 status = filename_convert(ctx, conn,
2806 req->flags2 & FLAGS2_DFS_PATHNAMES,
2808 UCF_COND_ALLOW_WCARD_LCOMP,
2809 &path_contains_wcard,
2811 if (!NT_STATUS_IS_OK(status)) {
2812 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2813 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2814 ERRSRV, ERRbadpath);
2817 reply_nterror(req, status);
2821 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2823 status = unlink_internals(conn, req, dirtype, smb_fname,
2824 path_contains_wcard);
2825 if (!NT_STATUS_IS_OK(status)) {
2826 if (open_was_deferred(req->mid)) {
2827 /* We have re-scheduled this call. */
2830 reply_nterror(req, status);
2834 reply_outbuf(req, 0, 0);
2836 TALLOC_FREE(smb_fname);
2837 END_PROFILE(SMBunlink);
2841 /****************************************************************************
2843 ****************************************************************************/
2845 static void fail_readraw(void)
2847 const char *errstr = talloc_asprintf(talloc_tos(),
2848 "FAIL ! reply_readbraw: socket write fail (%s)",
2853 exit_server_cleanly(errstr);
2856 /****************************************************************************
2857 Fake (read/write) sendfile. Returns -1 on read or write fail.
2858 ****************************************************************************/
2860 ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread)
2863 size_t tosend = nread;
2870 bufsize = MIN(nread, 65536);
2872 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2876 while (tosend > 0) {
2880 if (tosend > bufsize) {
2885 ret = read_file(fsp,buf,startpos,cur_read);
2891 /* If we had a short read, fill with zeros. */
2892 if (ret < cur_read) {
2893 memset(buf + ret, '\0', cur_read - ret);
2896 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2898 char addr[INET6_ADDRSTRLEN];
2900 * Try and give an error message saying what
2903 DEBUG(0, ("write_data failed for client %s. "
2905 get_peer_addr(fsp->conn->sconn->sock, addr,
2912 startpos += cur_read;
2916 return (ssize_t)nread;
2919 /****************************************************************************
2920 Deal with the case of sendfile reading less bytes from the file than
2921 requested. Fill with zeros (all we can do).
2922 ****************************************************************************/
2924 void sendfile_short_send(files_struct *fsp,
2929 #define SHORT_SEND_BUFSIZE 1024
2930 if (nread < headersize) {
2931 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2932 "header for file %s (%s). Terminating\n",
2933 fsp_str_dbg(fsp), strerror(errno)));
2934 exit_server_cleanly("sendfile_short_send failed");
2937 nread -= headersize;
2939 if (nread < smb_maxcnt) {
2940 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2942 exit_server_cleanly("sendfile_short_send: "
2946 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2947 "with zeros !\n", fsp_str_dbg(fsp)));
2949 while (nread < smb_maxcnt) {
2951 * We asked for the real file size and told sendfile
2952 * to not go beyond the end of the file. But it can
2953 * happen that in between our fstat call and the
2954 * sendfile call the file was truncated. This is very
2955 * bad because we have already announced the larger
2956 * number of bytes to the client.
2958 * The best we can do now is to send 0-bytes, just as
2959 * a read from a hole in a sparse file would do.
2961 * This should happen rarely enough that I don't care
2962 * about efficiency here :-)
2966 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2967 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2969 char addr[INET6_ADDRSTRLEN];
2971 * Try and give an error message saying what
2974 DEBUG(0, ("write_data failed for client %s. "
2977 fsp->conn->sconn->sock, addr,
2980 exit_server_cleanly("sendfile_short_send: "
2981 "write_data failed");
2989 /****************************************************************************
2990 Return a readbraw error (4 bytes of zero).
2991 ****************************************************************************/
2993 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2999 smbd_lock_socket(sconn);
3000 if (write_data(sconn->sock,header,4) != 4) {
3001 char addr[INET6_ADDRSTRLEN];
3003 * Try and give an error message saying what
3006 DEBUG(0, ("write_data failed for client %s. "
3008 get_peer_addr(sconn->sock, addr, sizeof(addr)),
3013 smbd_unlock_socket(sconn);
3016 /****************************************************************************
3017 Use sendfile in readbraw.
3018 ****************************************************************************/
3020 static void send_file_readbraw(connection_struct *conn,
3021 struct smb_request *req,
3027 struct smbd_server_connection *sconn = req->sconn;
3028 char *outbuf = NULL;
3032 * We can only use sendfile on a non-chained packet
3033 * but we can use on a non-oplocked file. tridge proved this
3034 * on a train in Germany :-). JRA.
3035 * reply_readbraw has already checked the length.
3038 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3039 (fsp->wcp == NULL) &&
3040 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3041 ssize_t sendfile_read = -1;
3043 DATA_BLOB header_blob;
3045 _smb_setlen(header,nread);
3046 header_blob = data_blob_const(header, 4);
3048 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3049 &header_blob, startpos,
3051 if (sendfile_read == -1) {
3052 /* Returning ENOSYS means no data at all was sent.
3053 * Do this as a normal read. */
3054 if (errno == ENOSYS) {
3055 goto normal_readbraw;
3059 * Special hack for broken Linux with no working sendfile. If we
3060 * return EINTR we sent the header but not the rest of the data.
3061 * Fake this up by doing read/write calls.
3063 if (errno == EINTR) {
3064 /* Ensure we don't do this again. */
3065 set_use_sendfile(SNUM(conn), False);
3066 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3068 if (fake_sendfile(fsp, startpos, nread) == -1) {
3069 DEBUG(0,("send_file_readbraw: "
3070 "fake_sendfile failed for "
3074 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3079 DEBUG(0,("send_file_readbraw: sendfile failed for "
3080 "file %s (%s). Terminating\n",
3081 fsp_str_dbg(fsp), strerror(errno)));
3082 exit_server_cleanly("send_file_readbraw sendfile failed");
3083 } else if (sendfile_read == 0) {
3085 * Some sendfile implementations return 0 to indicate
3086 * that there was a short read, but nothing was
3087 * actually written to the socket. In this case,
3088 * fallback to the normal read path so the header gets
3089 * the correct byte count.
3091 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3092 "bytes falling back to the normal read: "
3093 "%s\n", fsp_str_dbg(fsp)));
3094 goto normal_readbraw;
3097 /* Deal with possible short send. */
3098 if (sendfile_read != 4+nread) {
3099 sendfile_short_send(fsp, sendfile_read, 4, nread);
3106 outbuf = talloc_array(NULL, char, nread+4);
3108 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3109 (unsigned)(nread+4)));
3110 reply_readbraw_error(sconn);
3115 ret = read_file(fsp,outbuf+4,startpos,nread);
3116 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3125 _smb_setlen(outbuf,ret);
3126 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3127 char addr[INET6_ADDRSTRLEN];
3129 * Try and give an error message saying what
3132 DEBUG(0, ("write_data failed for client %s. "
3134 get_peer_addr(fsp->conn->sconn->sock, addr,
3141 TALLOC_FREE(outbuf);
3144 /****************************************************************************
3145 Reply to a readbraw (core+ protocol).
3146 ****************************************************************************/
3148 void reply_readbraw(struct smb_request *req)
3150 connection_struct *conn = req->conn;
3151 struct smbd_server_connection *sconn = req->sconn;
3152 ssize_t maxcount,mincount;
3156 struct lock_struct lock;
3159 START_PROFILE(SMBreadbraw);
3161 if (srv_is_signing_active(sconn) ||
3162 is_encrypted_packet(req->inbuf)) {
3163 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3164 "raw reads/writes are disallowed.");
3168 reply_readbraw_error(sconn);
3169 END_PROFILE(SMBreadbraw);
3173 if (sconn->smb1.echo_handler.trusted_fde) {
3174 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3175 "'async smb echo handler = yes'\n"));
3176 reply_readbraw_error(sconn);
3177 END_PROFILE(SMBreadbraw);
3182 * Special check if an oplock break has been issued
3183 * and the readraw request croses on the wire, we must
3184 * return a zero length response here.
3187 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3190 * We have to do a check_fsp by hand here, as
3191 * we must always return 4 zero bytes on error,
3195 if (!fsp || !conn || conn != fsp->conn ||
3196 req->vuid != fsp->vuid ||
3197 fsp->is_directory || fsp->fh->fd == -1) {
3199 * fsp could be NULL here so use the value from the packet. JRA.
3201 DEBUG(3,("reply_readbraw: fnum %d not valid "
3203 (int)SVAL(req->vwv+0, 0)));
3204 reply_readbraw_error(sconn);
3205 END_PROFILE(SMBreadbraw);
3209 /* Do a "by hand" version of CHECK_READ. */
3210 if (!(fsp->can_read ||
3211 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3212 (fsp->access_mask & FILE_EXECUTE)))) {
3213 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3214 (int)SVAL(req->vwv+0, 0)));
3215 reply_readbraw_error(sconn);
3216 END_PROFILE(SMBreadbraw);
3220 flush_write_cache(fsp, READRAW_FLUSH);
3222 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3223 if(req->wct == 10) {
3225 * This is a large offset (64 bit) read.
3227 #ifdef LARGE_SMB_OFF_T
3229 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3231 #else /* !LARGE_SMB_OFF_T */
3234 * Ensure we haven't been sent a >32 bit offset.
3237 if(IVAL(req->vwv+8, 0) != 0) {
3238 DEBUG(0,("reply_readbraw: large offset "
3239 "(%x << 32) used and we don't support "
3240 "64 bit offsets.\n",
3241 (unsigned int)IVAL(req->vwv+8, 0) ));
3242 reply_readbraw_error(sconn);
3243 END_PROFILE(SMBreadbraw);
3247 #endif /* LARGE_SMB_OFF_T */
3250 DEBUG(0,("reply_readbraw: negative 64 bit "
3251 "readraw offset (%.0f) !\n",
3252 (double)startpos ));
3253 reply_readbraw_error(sconn);
3254 END_PROFILE(SMBreadbraw);
3259 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3260 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3262 /* ensure we don't overrun the packet size */
3263 maxcount = MIN(65535,maxcount);
3265 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3266 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3269 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3270 reply_readbraw_error(sconn);
3271 END_PROFILE(SMBreadbraw);
3275 if (fsp_stat(fsp) == 0) {
3276 size = fsp->fsp_name->st.st_ex_size;
3279 if (startpos >= size) {
3282 nread = MIN(maxcount,(size - startpos));
3285 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3286 if (nread < mincount)
3290 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3291 "min=%lu nread=%lu\n",
3292 fsp->fnum, (double)startpos,
3293 (unsigned long)maxcount,
3294 (unsigned long)mincount,
3295 (unsigned long)nread ) );
3297 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3299 DEBUG(5,("reply_readbraw finished\n"));
3301 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3303 END_PROFILE(SMBreadbraw);
3308 #define DBGC_CLASS DBGC_LOCKING
3310 /****************************************************************************
3311 Reply to a lockread (core+ protocol).
3312 ****************************************************************************/
3314 void reply_lockread(struct smb_request *req)
3316 connection_struct *conn = req->conn;
3323 struct byte_range_lock *br_lck = NULL;
3325 struct smbd_server_connection *sconn = req->sconn;
3327 START_PROFILE(SMBlockread);
3330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3331 END_PROFILE(SMBlockread);
3335 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3337 if (!check_fsp(conn, req, fsp)) {
3338 END_PROFILE(SMBlockread);
3342 if (!CHECK_READ(fsp,req)) {
3343 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3344 END_PROFILE(SMBlockread);
3348 numtoread = SVAL(req->vwv+1, 0);
3349 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3351 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3353 reply_outbuf(req, 5, numtoread + 3);
3355 data = smb_buf(req->outbuf) + 3;
3358 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3359 * protocol request that predates the read/write lock concept.
3360 * Thus instead of asking for a read lock here we need to ask
3361 * for a write lock. JRA.
3362 * Note that the requested lock size is unaffected by max_recv.
3365 br_lck = do_lock(req->sconn->msg_ctx,
3367 (uint64_t)req->smbpid,
3368 (uint64_t)numtoread,
3372 False, /* Non-blocking lock. */
3376 TALLOC_FREE(br_lck);
3378 if (NT_STATUS_V(status)) {
3379 reply_nterror(req, status);
3380 END_PROFILE(SMBlockread);
3385 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3388 if (numtoread > sconn->smb1.negprot.max_recv) {
3389 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3390 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3391 (unsigned int)numtoread,
3392 (unsigned int)sconn->smb1.negprot.max_recv));
3393 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3395 nread = read_file(fsp,data,startpos,numtoread);
3398 reply_nterror(req, map_nt_error_from_unix(errno));
3399 END_PROFILE(SMBlockread);
3403 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3405 SSVAL(req->outbuf,smb_vwv0,nread);
3406 SSVAL(req->outbuf,smb_vwv5,nread+3);
3407 p = smb_buf(req->outbuf);
3408 SCVAL(p,0,0); /* pad byte. */
3411 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3412 fsp->fnum, (int)numtoread, (int)nread));
3414 END_PROFILE(SMBlockread);
3419 #define DBGC_CLASS DBGC_ALL
3421 /****************************************************************************
3423 ****************************************************************************/
3425 void reply_read(struct smb_request *req)
3427 connection_struct *conn = req->conn;
3434 struct lock_struct lock;
3435 struct smbd_server_connection *sconn = req->sconn;
3437 START_PROFILE(SMBread);
3440 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3441 END_PROFILE(SMBread);
3445 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3447 if (!check_fsp(conn, req, fsp)) {
3448 END_PROFILE(SMBread);
3452 if (!CHECK_READ(fsp,req)) {
3453 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3454 END_PROFILE(SMBread);
3458 numtoread = SVAL(req->vwv+1, 0);
3459 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3461 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3464 * The requested read size cannot be greater than max_recv. JRA.
3466 if (numtoread > sconn->smb1.negprot.max_recv) {
3467 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3468 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3469 (unsigned int)numtoread,
3470 (unsigned int)sconn->smb1.negprot.max_recv));
3471 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3474 reply_outbuf(req, 5, numtoread+3);
3476 data = smb_buf(req->outbuf) + 3;
3478 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3479 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3482 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3483 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3484 END_PROFILE(SMBread);
3489 nread = read_file(fsp,data,startpos,numtoread);
3492 reply_nterror(req, map_nt_error_from_unix(errno));
3496 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3498 SSVAL(req->outbuf,smb_vwv0,nread);
3499 SSVAL(req->outbuf,smb_vwv5,nread+3);
3500 SCVAL(smb_buf(req->outbuf),0,1);
3501 SSVAL(smb_buf(req->outbuf),1,nread);
3503 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3504 fsp->fnum, (int)numtoread, (int)nread ) );
3507 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3509 END_PROFILE(SMBread);
3513 /****************************************************************************
3515 ****************************************************************************/
3517 static int setup_readX_header(struct smb_request *req, char *outbuf,
3523 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3524 data = smb_buf(outbuf);
3526 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3528 SCVAL(outbuf,smb_vwv0,0xFF);
3529 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3530 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3531 SSVAL(outbuf,smb_vwv6,
3533 + 1 /* the wct field */
3534 + 12 * sizeof(uint16_t) /* vwv */
3535 + 2); /* the buflen field */
3536 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3537 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3538 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3539 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3543 /****************************************************************************
3544 Reply to a read and X - possibly using sendfile.
3545 ****************************************************************************/
3547 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3548 files_struct *fsp, SMB_OFF_T startpos,
3552 struct lock_struct lock;
3553 int saved_errno = 0;
3555 if(fsp_stat(fsp) == -1) {
3556 reply_nterror(req, map_nt_error_from_unix(errno));
3560 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3561 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3564 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3565 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3569 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3570 (startpos > fsp->fsp_name->st.st_ex_size)
3571 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3573 * We already know that we would do a short read, so don't
3574 * try the sendfile() path.
3576 goto nosendfile_read;
3580 * We can only use sendfile on a non-chained packet
3581 * but we can use on a non-oplocked file. tridge proved this
3582 * on a train in Germany :-). JRA.
3585 if (!req_is_in_chain(req) &&
3586 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3587 (fsp->wcp == NULL) &&
3588 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3589 uint8 headerbuf[smb_size + 12 * 2];
3593 * Set up the packet header before send. We
3594 * assume here the sendfile will work (get the
3595 * correct amount of data).
3598 header = data_blob_const(headerbuf, sizeof(headerbuf));
3600 construct_reply_common_req(req, (char *)headerbuf);
3601 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3603 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3604 startpos, smb_maxcnt);
3606 /* Returning ENOSYS means no data at all was sent.
3607 Do this as a normal read. */
3608 if (errno == ENOSYS) {
3613 * Special hack for broken Linux with no working sendfile. If we
3614 * return EINTR we sent the header but not the rest of the data.
3615 * Fake this up by doing read/write calls.
3618 if (errno == EINTR) {
3619 /* Ensure we don't do this again. */
3620 set_use_sendfile(SNUM(conn), False);
3621 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3622 nread = fake_sendfile(fsp, startpos,
3625 DEBUG(0,("send_file_readX: "
3626 "fake_sendfile failed for "
3630 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3632 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3633 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3634 /* No outbuf here means successful sendfile. */
3638 DEBUG(0,("send_file_readX: sendfile failed for file "
3639 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3641 exit_server_cleanly("send_file_readX sendfile failed");
3642 } else if (nread == 0) {
3644 * Some sendfile implementations return 0 to indicate
3645 * that there was a short read, but nothing was
3646 * actually written to the socket. In this case,
3647 * fallback to the normal read path so the header gets
3648 * the correct byte count.
3650 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3651 "falling back to the normal read: %s\n",
3656 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3657 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3659 /* Deal with possible short send. */
3660 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3661 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3663 /* No outbuf here means successful sendfile. */
3664 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3665 SMB_PERFCOUNT_END(&req->pcd);
3671 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3672 uint8 headerbuf[smb_size + 2*12];
3674 construct_reply_common_req(req, (char *)headerbuf);
3675 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3677 /* Send out the header. */
3678 if (write_data(req->sconn->sock, (char *)headerbuf,
3679 sizeof(headerbuf)) != sizeof(headerbuf)) {
3681 char addr[INET6_ADDRSTRLEN];
3683 * Try and give an error message saying what
3686 DEBUG(0, ("write_data failed for client %s. "
3688 get_peer_addr(req->sconn->sock, addr,
3692 DEBUG(0,("send_file_readX: write_data failed for file "
3693 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3695 exit_server_cleanly("send_file_readX sendfile failed");
3697 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3699 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3700 "file %s (%s).\n", fsp_str_dbg(fsp),
3702 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3709 reply_outbuf(req, 12, smb_maxcnt);
3711 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3712 saved_errno = errno;
3714 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3717 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3721 setup_readX_header(req, (char *)req->outbuf, nread);
3723 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3724 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3730 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3731 TALLOC_FREE(req->outbuf);
3735 /****************************************************************************
3736 Reply to a read and X.
3737 ****************************************************************************/
3739 void reply_read_and_X(struct smb_request *req)
3741 connection_struct *conn = req->conn;
3745 bool big_readX = False;
3747 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3750 START_PROFILE(SMBreadX);
3752 if ((req->wct != 10) && (req->wct != 12)) {
3753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3757 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3758 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3759 smb_maxcnt = SVAL(req->vwv+5, 0);
3761 /* If it's an IPC, pass off the pipe handler. */
3763 reply_pipe_read_and_X(req);
3764 END_PROFILE(SMBreadX);
3768 if (!check_fsp(conn, req, fsp)) {
3769 END_PROFILE(SMBreadX);
3773 if (!CHECK_READ(fsp,req)) {
3774 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3775 END_PROFILE(SMBreadX);
3779 if (global_client_caps & CAP_LARGE_READX) {
3780 size_t upper_size = SVAL(req->vwv+7, 0);
3781 smb_maxcnt |= (upper_size<<16);
3782 if (upper_size > 1) {
3783 /* Can't do this on a chained packet. */
3784 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3785 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3786 END_PROFILE(SMBreadX);
3789 /* We currently don't do this on signed or sealed data. */
3790 if (srv_is_signing_active(req->sconn) ||
3791 is_encrypted_packet(req->inbuf)) {
3792 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3793 END_PROFILE(SMBreadX);
3796 /* Is there room in the reply for this data ? */
3797 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3799 NT_STATUS_INVALID_PARAMETER);
3800 END_PROFILE(SMBreadX);
3807 if (req->wct == 12) {
3808 #ifdef LARGE_SMB_OFF_T
3810 * This is a large offset (64 bit) read.
3812 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3814 #else /* !LARGE_SMB_OFF_T */
3817 * Ensure we haven't been sent a >32 bit offset.
3820 if(IVAL(req->vwv+10, 0) != 0) {
3821 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3822 "used and we don't support 64 bit offsets.\n",
3823 (unsigned int)IVAL(req->vwv+10, 0) ));
3824 END_PROFILE(SMBreadX);
3825 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3829 #endif /* LARGE_SMB_OFF_T */
3834 NTSTATUS status = schedule_aio_read_and_X(conn,
3839 if (NT_STATUS_IS_OK(status)) {
3840 /* Read scheduled - we're done. */
3843 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3844 /* Real error - report to client. */
3845 END_PROFILE(SMBreadX);
3846 reply_nterror(req, status);
3849 /* NT_STATUS_RETRY - fall back to sync read. */
3852 smbd_lock_socket(req->sconn);
3853 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3854 smbd_unlock_socket(req->sconn);
3857 END_PROFILE(SMBreadX);
3861 /****************************************************************************
3862 Error replies to writebraw must have smb_wct == 1. Fix this up.
3863 ****************************************************************************/
3865 void error_to_writebrawerr(struct smb_request *req)
3867 uint8 *old_outbuf = req->outbuf;
3869 reply_outbuf(req, 1, 0);
3871 memcpy(req->outbuf, old_outbuf, smb_size);
3872 TALLOC_FREE(old_outbuf);
3875 /****************************************************************************
3876 Read 4 bytes of a smb packet and return the smb length of the packet.
3877 Store the result in the buffer. This version of the function will
3878 never return a session keepalive (length of zero).
3879 Timeout is in milliseconds.
3880 ****************************************************************************/
3882 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3885 uint8_t msgtype = SMBkeepalive;
3887 while (msgtype == SMBkeepalive) {
3890 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3892 if (!NT_STATUS_IS_OK(status)) {
3893 char addr[INET6_ADDRSTRLEN];
3894 /* Try and give an error message
3895 * saying what client failed. */
3896 DEBUG(0, ("read_fd_with_timeout failed for "
3897 "client %s read error = %s.\n",
3898 get_peer_addr(fd,addr,sizeof(addr)),
3899 nt_errstr(status)));
3903 msgtype = CVAL(inbuf, 0);
3906 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3907 (unsigned long)len));
3909 return NT_STATUS_OK;
3912 /****************************************************************************
3913 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3914 ****************************************************************************/
3916 void reply_writebraw(struct smb_request *req)
3918 connection_struct *conn = req->conn;
3921 ssize_t total_written=0;
3922 size_t numtowrite=0;
3925 const char *data=NULL;
3928 struct lock_struct lock;
3931 START_PROFILE(SMBwritebraw);
3934 * If we ever reply with an error, it must have the SMB command
3935 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3938 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3940 if (srv_is_signing_active(req->sconn)) {
3941 END_PROFILE(SMBwritebraw);
3942 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3943 "raw reads/writes are disallowed.");
3946 if (req->wct < 12) {
3947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3948 error_to_writebrawerr(req);
3949 END_PROFILE(SMBwritebraw);
3953 if (req->sconn->smb1.echo_handler.trusted_fde) {
3954 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3955 "'async smb echo handler = yes'\n"));
3956 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3957 error_to_writebrawerr(req);
3958 END_PROFILE(SMBwritebraw);
3962 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3963 if (!check_fsp(conn, req, fsp)) {
3964 error_to_writebrawerr(req);
3965 END_PROFILE(SMBwritebraw);
3969 if (!CHECK_WRITE(fsp)) {
3970 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3971 error_to_writebrawerr(req);
3972 END_PROFILE(SMBwritebraw);
3976 tcount = IVAL(req->vwv+1, 0);
3977 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3978 write_through = BITSETW(req->vwv+7,0);
3980 /* We have to deal with slightly different formats depending
3981 on whether we are using the core+ or lanman1.0 protocol */
3983 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3984 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3985 data = smb_buf_const(req->inbuf);
3987 numtowrite = SVAL(req->vwv+10, 0);
3988 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3991 /* Ensure we don't write bytes past the end of this packet. */
3992 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3993 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3994 error_to_writebrawerr(req);
3995 END_PROFILE(SMBwritebraw);
3999 if (!fsp->print_file) {
4000 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4001 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4004 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4005 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4006 error_to_writebrawerr(req);
4007 END_PROFILE(SMBwritebraw);
4013 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4016 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
4017 "wrote=%d sync=%d\n",
4018 fsp->fnum, (double)startpos, (int)numtowrite,
4019 (int)nwritten, (int)write_through));
4021 if (nwritten < (ssize_t)numtowrite) {
4022 reply_nterror(req, NT_STATUS_DISK_FULL);
4023 error_to_writebrawerr(req);
4027 total_written = nwritten;
4029 /* Allocate a buffer of 64k + length. */
4030 buf = talloc_array(NULL, char, 65540);
4032 reply_nterror(req, NT_STATUS_NO_MEMORY);
4033 error_to_writebrawerr(req);
4037 /* Return a SMBwritebraw message to the redirector to tell
4038 * it to send more bytes */
4040 memcpy(buf, req->inbuf, smb_size);
4041 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4042 SCVAL(buf,smb_com,SMBwritebraw);
4043 SSVALS(buf,smb_vwv0,0xFFFF);
4045 if (!srv_send_smb(req->sconn,
4047 false, 0, /* no signing */
4048 IS_CONN_ENCRYPTED(conn),
4050 exit_server_cleanly("reply_writebraw: srv_send_smb "
4054 /* Now read the raw data into the buffer and write it */
4055 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4057 if (!NT_STATUS_IS_OK(status)) {
4058 exit_server_cleanly("secondary writebraw failed");
4061 /* Set up outbuf to return the correct size */
4062 reply_outbuf(req, 1, 0);
4064 if (numtowrite != 0) {
4066 if (numtowrite > 0xFFFF) {
4067 DEBUG(0,("reply_writebraw: Oversize secondary write "
4068 "raw requested (%u). Terminating\n",
4069 (unsigned int)numtowrite ));
4070 exit_server_cleanly("secondary writebraw failed");
4073 if (tcount > nwritten+numtowrite) {
4074 DEBUG(3,("reply_writebraw: Client overestimated the "
4076 (int)tcount,(int)nwritten,(int)numtowrite));
4079 status = read_data(req->sconn->sock, buf+4, numtowrite);
4081 if (!NT_STATUS_IS_OK(status)) {
4082 char addr[INET6_ADDRSTRLEN];
4083 /* Try and give an error message
4084 * saying what client failed. */
4085 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4086 "raw read failed (%s) for client %s. "
4087 "Terminating\n", nt_errstr(status),
4088 get_peer_addr(req->sconn->sock, addr,
4090 exit_server_cleanly("secondary writebraw failed");
4093 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4094 if (nwritten == -1) {
4096 reply_nterror(req, map_nt_error_from_unix(errno));
4097 error_to_writebrawerr(req);
4101 if (nwritten < (ssize_t)numtowrite) {
4102 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4103 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4107 total_written += nwritten;
4112 SSVAL(req->outbuf,smb_vwv0,total_written);
4114 status = sync_file(conn, fsp, write_through);
4115 if (!NT_STATUS_IS_OK(status)) {
4116 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4117 fsp_str_dbg(fsp), nt_errstr(status)));
4118 reply_nterror(req, status);
4119 error_to_writebrawerr(req);
4123 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4125 fsp->fnum, (double)startpos, (int)numtowrite,
4126 (int)total_written));
4128 if (!fsp->print_file) {
4129 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4132 /* We won't return a status if write through is not selected - this
4133 * follows what WfWg does */
4134 END_PROFILE(SMBwritebraw);
4136 if (!write_through && total_written==tcount) {
4138 #if RABBIT_PELLET_FIX
4140 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4141 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
4144 if (!send_keepalive(req->sconn->sock)) {
4145 exit_server_cleanly("reply_writebraw: send of "
4146 "keepalive failed");
4149 TALLOC_FREE(req->outbuf);
4154 if (!fsp->print_file) {
4155 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4158 END_PROFILE(SMBwritebraw);
4163 #define DBGC_CLASS DBGC_LOCKING
4165 /****************************************************************************
4166 Reply to a writeunlock (core+).
4167 ****************************************************************************/
4169 void reply_writeunlock(struct smb_request *req)
4171 connection_struct *conn = req->conn;
4172 ssize_t nwritten = -1;
4176 NTSTATUS status = NT_STATUS_OK;
4178 struct lock_struct lock;
4179 int saved_errno = 0;
4181 START_PROFILE(SMBwriteunlock);
4184 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4185 END_PROFILE(SMBwriteunlock);
4189 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4191 if (!check_fsp(conn, req, fsp)) {
4192 END_PROFILE(SMBwriteunlock);
4196 if (!CHECK_WRITE(fsp)) {
4197 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4198 END_PROFILE(SMBwriteunlock);
4202 numtowrite = SVAL(req->vwv+1, 0);
4203 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4204 data = (const char *)req->buf + 3;
4206 if (!fsp->print_file && numtowrite > 0) {
4207 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4208 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4211 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4212 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4213 END_PROFILE(SMBwriteunlock);
4218 /* The special X/Open SMB protocol handling of
4219 zero length writes is *NOT* done for
4221 if(numtowrite == 0) {
4224 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4225 saved_errno = errno;
4228 status = sync_file(conn, fsp, False /* write through */);
4229 if (!NT_STATUS_IS_OK(status)) {
4230 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4231 fsp_str_dbg(fsp), nt_errstr(status)));
4232 reply_nterror(req, status);
4237 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4241 if((nwritten < numtowrite) && (numtowrite != 0)) {
4242 reply_nterror(req, NT_STATUS_DISK_FULL);
4246 if (numtowrite && !fsp->print_file) {
4247 status = do_unlock(req->sconn->msg_ctx,
4249 (uint64_t)req->smbpid,
4250 (uint64_t)numtowrite,
4254 if (NT_STATUS_V(status)) {
4255 reply_nterror(req, status);
4260 reply_outbuf(req, 1, 0);
4262 SSVAL(req->outbuf,smb_vwv0,nwritten);
4264 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4265 fsp->fnum, (int)numtowrite, (int)nwritten));
4268 if (numtowrite && !fsp->print_file) {
4269 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4272 END_PROFILE(SMBwriteunlock);
4277 #define DBGC_CLASS DBGC_ALL
4279 /****************************************************************************
4281 ****************************************************************************/
4283 void reply_write(struct smb_request *req)
4285 connection_struct *conn = req->conn;
4287 ssize_t nwritten = -1;
4291 struct lock_struct lock;
4293 int saved_errno = 0;
4295 START_PROFILE(SMBwrite);
4298 END_PROFILE(SMBwrite);
4299 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4303 /* If it's an IPC, pass off the pipe handler. */
4305 reply_pipe_write(req);
4306 END_PROFILE(SMBwrite);
4310 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4312 if (!check_fsp(conn, req, fsp)) {
4313 END_PROFILE(SMBwrite);
4317 if (!CHECK_WRITE(fsp)) {
4318 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4319 END_PROFILE(SMBwrite);
4323 numtowrite = SVAL(req->vwv+1, 0);
4324 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4325 data = (const char *)req->buf + 3;
4327 if (!fsp->print_file) {
4328 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4329 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4332 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4333 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4334 END_PROFILE(SMBwrite);
4340 * X/Open SMB protocol says that if smb_vwv1 is
4341 * zero then the file size should be extended or
4342 * truncated to the size given in smb_vwv[2-3].
4345 if(numtowrite == 0) {
4347 * This is actually an allocate call, and set EOF. JRA.
4349 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4351 reply_nterror(req, NT_STATUS_DISK_FULL);
4354 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4356 reply_nterror(req, NT_STATUS_DISK_FULL);
4359 trigger_write_time_update_immediate(fsp);
4361 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4364 status = sync_file(conn, fsp, False);
4365 if (!NT_STATUS_IS_OK(status)) {
4366 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4367 fsp_str_dbg(fsp), nt_errstr(status)));
4368 reply_nterror(req, status);
4373 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4377 if((nwritten == 0) && (numtowrite != 0)) {
4378 reply_nterror(req, NT_STATUS_DISK_FULL);
4382 reply_outbuf(req, 1, 0);
4384 SSVAL(req->outbuf,smb_vwv0,nwritten);
4386 if (nwritten < (ssize_t)numtowrite) {
4387 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4388 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4391 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4394 if (!fsp->print_file) {
4395 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4398 END_PROFILE(SMBwrite);
4402 /****************************************************************************
4403 Ensure a buffer is a valid writeX for recvfile purposes.
4404 ****************************************************************************/
4406 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4407 (2*14) + /* word count (including bcc) */ \
4410 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4411 const uint8_t *inbuf)
4414 connection_struct *conn = NULL;
4415 unsigned int doff = 0;
4416 size_t len = smb_len_large(inbuf);
4418 if (is_encrypted_packet(inbuf)) {
4419 /* Can't do this on encrypted
4424 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4428 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4429 CVAL(inbuf,smb_wct) != 14) {
4430 DEBUG(10,("is_valid_writeX_buffer: chained or "
4431 "invalid word length.\n"));
4435 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4437 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4441 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4444 if (IS_PRINT(conn)) {
4445 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4448 doff = SVAL(inbuf,smb_vwv11);
4450 numtowrite = SVAL(inbuf,smb_vwv10);
4452 if (len > doff && len - doff > 0xFFFF) {
4453 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4456 if (numtowrite == 0) {
4457 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4461 /* Ensure the sizes match up. */
4462 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4463 /* no pad byte...old smbclient :-( */
4464 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4466 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4470 if (len - doff != numtowrite) {
4471 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4472 "len = %u, doff = %u, numtowrite = %u\n",
4475 (unsigned int)numtowrite ));
4479 DEBUG(10,("is_valid_writeX_buffer: true "
4480 "len = %u, doff = %u, numtowrite = %u\n",
4483 (unsigned int)numtowrite ));
4488 /****************************************************************************
4489 Reply to a write and X.
4490 ****************************************************************************/
4492 void reply_write_and_X(struct smb_request *req)
4494 connection_struct *conn = req->conn;
4496 struct lock_struct lock;
4501 unsigned int smb_doff;
4502 unsigned int smblen;
4505 int saved_errno = 0;
4507 START_PROFILE(SMBwriteX);
4509 if ((req->wct != 12) && (req->wct != 14)) {
4510 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4511 END_PROFILE(SMBwriteX);
4515 numtowrite = SVAL(req->vwv+10, 0);
4516 smb_doff = SVAL(req->vwv+11, 0);
4517 smblen = smb_len(req->inbuf);
4519 if (req->unread_bytes > 0xFFFF ||
4520 (smblen > smb_doff &&
4521 smblen - smb_doff > 0xFFFF)) {
4522 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4525 if (req->unread_bytes) {
4526 /* Can't do a recvfile write on IPC$ */
4528 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4529 END_PROFILE(SMBwriteX);
4532 if (numtowrite != req->unread_bytes) {
4533 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4534 END_PROFILE(SMBwriteX);
4538 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4539 smb_doff + numtowrite > smblen) {
4540 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4541 END_PROFILE(SMBwriteX);
4546 /* If it's an IPC, pass off the pipe handler. */
4548 if (req->unread_bytes) {
4549 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4550 END_PROFILE(SMBwriteX);
4553 reply_pipe_write_and_X(req);
4554 END_PROFILE(SMBwriteX);
4558 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4559 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4560 write_through = BITSETW(req->vwv+7,0);
4562 if (!check_fsp(conn, req, fsp)) {
4563 END_PROFILE(SMBwriteX);
4567 if (!CHECK_WRITE(fsp)) {
4568 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4569 END_PROFILE(SMBwriteX);
4573 data = smb_base(req->inbuf) + smb_doff;
4575 if(req->wct == 14) {
4576 #ifdef LARGE_SMB_OFF_T
4578 * This is a large offset (64 bit) write.
4580 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4582 #else /* !LARGE_SMB_OFF_T */
4585 * Ensure we haven't been sent a >32 bit offset.
4588 if(IVAL(req->vwv+12, 0) != 0) {
4589 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4590 "used and we don't support 64 bit offsets.\n",
4591 (unsigned int)IVAL(req->vwv+12, 0) ));
4592 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4593 END_PROFILE(SMBwriteX);
4597 #endif /* LARGE_SMB_OFF_T */
4600 /* X/Open SMB protocol says that, unlike SMBwrite
4601 if the length is zero then NO truncation is
4602 done, just a write of zero. To truncate a file,
4605 if(numtowrite == 0) {
4608 if (req->unread_bytes == 0) {
4609 status = schedule_aio_write_and_X(conn,
4616 if (NT_STATUS_IS_OK(status)) {
4617 /* write scheduled - we're done. */
4620 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4621 /* Real error - report to client. */
4622 reply_nterror(req, status);
4625 /* NT_STATUS_RETRY - fall through to sync write. */
4628 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4629 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4632 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4633 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4637 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4638 saved_errno = errno;
4640 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4644 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4648 if((nwritten == 0) && (numtowrite != 0)) {
4649 reply_nterror(req, NT_STATUS_DISK_FULL);
4653 reply_outbuf(req, 6, 0);
4654 SSVAL(req->outbuf,smb_vwv2,nwritten);
4655 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4657 if (nwritten < (ssize_t)numtowrite) {
4658 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4659 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4662 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4663 fsp->fnum, (int)numtowrite, (int)nwritten));
4665 status = sync_file(conn, fsp, write_through);
4666 if (!NT_STATUS_IS_OK(status)) {
4667 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4668 fsp_str_dbg(fsp), nt_errstr(status)));
4669 reply_nterror(req, status);
4673 END_PROFILE(SMBwriteX);
4678 END_PROFILE(SMBwriteX);
4682 /****************************************************************************
4684 ****************************************************************************/
4686 void reply_lseek(struct smb_request *req)
4688 connection_struct *conn = req->conn;
4694 START_PROFILE(SMBlseek);
4697 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4698 END_PROFILE(SMBlseek);
4702 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4704 if (!check_fsp(conn, req, fsp)) {
4708 flush_write_cache(fsp, SEEK_FLUSH);
4710 mode = SVAL(req->vwv+1, 0) & 3;
4711 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4712 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4721 res = fsp->fh->pos + startpos;
4732 if (umode == SEEK_END) {
4733 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4734 if(errno == EINVAL) {
4735 SMB_OFF_T current_pos = startpos;
4737 if(fsp_stat(fsp) == -1) {
4739 map_nt_error_from_unix(errno));
4740 END_PROFILE(SMBlseek);
4744 current_pos += fsp->fsp_name->st.st_ex_size;
4746 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4751 reply_nterror(req, map_nt_error_from_unix(errno));
4752 END_PROFILE(SMBlseek);
4759 reply_outbuf(req, 2, 0);
4760 SIVAL(req->outbuf,smb_vwv0,res);
4762 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4763 fsp->fnum, (double)startpos, (double)res, mode));
4765 END_PROFILE(SMBlseek);
4769 /****************************************************************************
4771 ****************************************************************************/
4773 void reply_flush(struct smb_request *req)
4775 connection_struct *conn = req->conn;
4779 START_PROFILE(SMBflush);
4782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4786 fnum = SVAL(req->vwv+0, 0);
4787 fsp = file_fsp(req, fnum);
4789 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4794 file_sync_all(conn);
4796 NTSTATUS status = sync_file(conn, fsp, True);
4797 if (!NT_STATUS_IS_OK(status)) {
4798 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4799 fsp_str_dbg(fsp), nt_errstr(status)));
4800 reply_nterror(req, status);
4801 END_PROFILE(SMBflush);
4806 reply_outbuf(req, 0, 0);
4808 DEBUG(3,("flush\n"));
4809 END_PROFILE(SMBflush);
4813 /****************************************************************************
4815 conn POINTER CAN BE NULL HERE !
4816 ****************************************************************************/
4818 void reply_exit(struct smb_request *req)
4820 START_PROFILE(SMBexit);
4822 file_close_pid(req->sconn, req->smbpid, req->vuid);
4824 reply_outbuf(req, 0, 0);
4826 DEBUG(3,("exit\n"));
4828 END_PROFILE(SMBexit);
4832 /****************************************************************************
4833 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4834 ****************************************************************************/
4836 void reply_close(struct smb_request *req)
4838 connection_struct *conn = req->conn;
4839 NTSTATUS status = NT_STATUS_OK;
4840 files_struct *fsp = NULL;
4841 START_PROFILE(SMBclose);
4844 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4845 END_PROFILE(SMBclose);
4849 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4852 * We can only use check_fsp if we know it's not a directory.
4855 if (!check_fsp_open(conn, req, fsp)) {
4856 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4857 END_PROFILE(SMBclose);
4861 if(fsp->is_directory) {
4863 * Special case - close NT SMB directory handle.
4865 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4866 status = close_file(req, fsp, NORMAL_CLOSE);
4870 * Close ordinary file.
4873 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4874 fsp->fh->fd, fsp->fnum,
4875 conn->num_files_open));
4878 * Take care of any time sent in the close.
4881 t = srv_make_unix_date3(req->vwv+1);
4882 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4885 * close_file() returns the unix errno if an error
4886 * was detected on close - normally this is due to
4887 * a disk full error. If not then it was probably an I/O error.
4890 status = close_file(req, fsp, NORMAL_CLOSE);
4893 if (!NT_STATUS_IS_OK(status)) {
4894 reply_nterror(req, status);
4895 END_PROFILE(SMBclose);
4899 reply_outbuf(req, 0, 0);
4900 END_PROFILE(SMBclose);
4904 /****************************************************************************
4905 Reply to a writeclose (Core+ protocol).
4906 ****************************************************************************/
4908 void reply_writeclose(struct smb_request *req)
4910 connection_struct *conn = req->conn;
4912 ssize_t nwritten = -1;
4913 NTSTATUS close_status = NT_STATUS_OK;
4916 struct timespec mtime;
4918 struct lock_struct lock;
4920 START_PROFILE(SMBwriteclose);
4923 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4924 END_PROFILE(SMBwriteclose);
4928 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4930 if (!check_fsp(conn, req, fsp)) {
4931 END_PROFILE(SMBwriteclose);
4934 if (!CHECK_WRITE(fsp)) {
4935 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4936 END_PROFILE(SMBwriteclose);
4940 numtowrite = SVAL(req->vwv+1, 0);
4941 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4942 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4943 data = (const char *)req->buf + 1;
4945 if (!fsp->print_file) {
4946 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4947 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4950 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4951 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4952 END_PROFILE(SMBwriteclose);
4957 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4959 set_close_write_time(fsp, mtime);
4962 * More insanity. W2K only closes the file if writelen > 0.
4967 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4968 "file %s\n", fsp_str_dbg(fsp)));
4969 close_status = close_file(req, fsp, NORMAL_CLOSE);
4972 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4973 fsp->fnum, (int)numtowrite, (int)nwritten,
4974 conn->num_files_open));
4976 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4977 reply_nterror(req, NT_STATUS_DISK_FULL);
4981 if(!NT_STATUS_IS_OK(close_status)) {
4982 reply_nterror(req, close_status);
4986 reply_outbuf(req, 1, 0);
4988 SSVAL(req->outbuf,smb_vwv0,nwritten);
4991 if (numtowrite && !fsp->print_file) {
4992 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4995 END_PROFILE(SMBwriteclose);
5000 #define DBGC_CLASS DBGC_LOCKING
5002 /****************************************************************************
5004 ****************************************************************************/
5006 void reply_lock(struct smb_request *req)
5008 connection_struct *conn = req->conn;
5009 uint64_t count,offset;
5012 struct byte_range_lock *br_lck = NULL;
5014 START_PROFILE(SMBlock);
5017 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5018 END_PROFILE(SMBlock);
5022 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5024 if (!check_fsp(conn, req, fsp)) {
5025 END_PROFILE(SMBlock);
5029 count = (uint64_t)IVAL(req->vwv+1, 0);
5030 offset = (uint64_t)IVAL(req->vwv+3, 0);
5032 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5033 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
5035 br_lck = do_lock(req->sconn->msg_ctx,
5037 (uint64_t)req->smbpid,
5042 False, /* Non-blocking lock. */
5047 TALLOC_FREE(br_lck);
5049 if (NT_STATUS_V(status)) {
5050 reply_nterror(req, status);
5051 END_PROFILE(SMBlock);
5055 reply_outbuf(req, 0, 0);
5057 END_PROFILE(SMBlock);
5061 /****************************************************************************
5063 ****************************************************************************/
5065 void reply_unlock(struct smb_request *req)
5067 connection_struct *conn = req->conn;
5068 uint64_t count,offset;
5072 START_PROFILE(SMBunlock);
5075 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5076 END_PROFILE(SMBunlock);
5080 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5082 if (!check_fsp(conn, req, fsp)) {
5083 END_PROFILE(SMBunlock);
5087 count = (uint64_t)IVAL(req->vwv+1, 0);
5088 offset = (uint64_t)IVAL(req->vwv+3, 0);
5090 status = do_unlock(req->sconn->msg_ctx,
5092 (uint64_t)req->smbpid,
5097 if (NT_STATUS_V(status)) {
5098 reply_nterror(req, status);
5099 END_PROFILE(SMBunlock);
5103 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5104 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5106 reply_outbuf(req, 0, 0);
5108 END_PROFILE(SMBunlock);
5113 #define DBGC_CLASS DBGC_ALL
5115 /****************************************************************************
5117 conn POINTER CAN BE NULL HERE !
5118 ****************************************************************************/
5120 void reply_tdis(struct smb_request *req)
5122 connection_struct *conn = req->conn;
5123 START_PROFILE(SMBtdis);
5126 DEBUG(4,("Invalid connection in tdis\n"));
5127 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5128 END_PROFILE(SMBtdis);
5134 close_cnum(conn,req->vuid);
5137 reply_outbuf(req, 0, 0);
5138 END_PROFILE(SMBtdis);
5142 /****************************************************************************
5144 conn POINTER CAN BE NULL HERE !
5145 ****************************************************************************/
5147 void reply_echo(struct smb_request *req)
5149 connection_struct *conn = req->conn;
5150 struct smb_perfcount_data local_pcd;
5151 struct smb_perfcount_data *cur_pcd;
5155 START_PROFILE(SMBecho);
5157 smb_init_perfcount_data(&local_pcd);
5160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5161 END_PROFILE(SMBecho);
5165 smb_reverb = SVAL(req->vwv+0, 0);
5167 reply_outbuf(req, 1, req->buflen);
5169 /* copy any incoming data back out */
5170 if (req->buflen > 0) {
5171 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5174 if (smb_reverb > 100) {
5175 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5179 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5181 /* this makes sure we catch the request pcd */
5182 if (seq_num == smb_reverb) {
5183 cur_pcd = &req->pcd;
5185 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5186 cur_pcd = &local_pcd;
5189 SSVAL(req->outbuf,smb_vwv0,seq_num);
5191 show_msg((char *)req->outbuf);
5192 if (!srv_send_smb(req->sconn,
5193 (char *)req->outbuf,
5194 true, req->seqnum+1,
5195 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5197 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5200 DEBUG(3,("echo %d times\n", smb_reverb));
5202 TALLOC_FREE(req->outbuf);
5204 END_PROFILE(SMBecho);
5208 /****************************************************************************
5209 Reply to a printopen.
5210 ****************************************************************************/
5212 void reply_printopen(struct smb_request *req)
5214 connection_struct *conn = req->conn;
5218 START_PROFILE(SMBsplopen);
5221 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5222 END_PROFILE(SMBsplopen);
5226 if (!CAN_PRINT(conn)) {
5227 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5228 END_PROFILE(SMBsplopen);
5232 status = file_new(req, conn, &fsp);
5233 if(!NT_STATUS_IS_OK(status)) {
5234 reply_nterror(req, status);
5235 END_PROFILE(SMBsplopen);
5239 /* Open for exclusive use, write only. */
5240 status = print_spool_open(fsp, NULL, req->vuid);
5242 if (!NT_STATUS_IS_OK(status)) {
5243 file_free(req, fsp);
5244 reply_nterror(req, status);
5245 END_PROFILE(SMBsplopen);
5249 reply_outbuf(req, 1, 0);
5250 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5252 DEBUG(3,("openprint fd=%d fnum=%d\n",
5253 fsp->fh->fd, fsp->fnum));
5255 END_PROFILE(SMBsplopen);
5259 /****************************************************************************
5260 Reply to a printclose.
5261 ****************************************************************************/
5263 void reply_printclose(struct smb_request *req)
5265 connection_struct *conn = req->conn;
5269 START_PROFILE(SMBsplclose);
5272 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5273 END_PROFILE(SMBsplclose);
5277 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5279 if (!check_fsp(conn, req, fsp)) {
5280 END_PROFILE(SMBsplclose);
5284 if (!CAN_PRINT(conn)) {
5285 reply_force_doserror(req, ERRSRV, ERRerror);
5286 END_PROFILE(SMBsplclose);
5290 DEBUG(3,("printclose fd=%d fnum=%d\n",
5291 fsp->fh->fd,fsp->fnum));
5293 status = close_file(req, fsp, NORMAL_CLOSE);
5295 if(!NT_STATUS_IS_OK(status)) {
5296 reply_nterror(req, status);
5297 END_PROFILE(SMBsplclose);
5301 reply_outbuf(req, 0, 0);
5303 END_PROFILE(SMBsplclose);
5307 /****************************************************************************
5308 Reply to a printqueue.
5309 ****************************************************************************/
5311 void reply_printqueue(struct smb_request *req)
5313 connection_struct *conn = req->conn;
5317 START_PROFILE(SMBsplretq);
5320 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5321 END_PROFILE(SMBsplretq);
5325 max_count = SVAL(req->vwv+0, 0);
5326 start_index = SVAL(req->vwv+1, 0);
5328 /* we used to allow the client to get the cnum wrong, but that
5329 is really quite gross and only worked when there was only
5330 one printer - I think we should now only accept it if they
5331 get it right (tridge) */
5332 if (!CAN_PRINT(conn)) {
5333 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5334 END_PROFILE(SMBsplretq);
5338 reply_outbuf(req, 2, 3);
5339 SSVAL(req->outbuf,smb_vwv0,0);
5340 SSVAL(req->outbuf,smb_vwv1,0);
5341 SCVAL(smb_buf(req->outbuf),0,1);
5342 SSVAL(smb_buf(req->outbuf),1,0);
5344 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5345 start_index, max_count));
5348 TALLOC_CTX *mem_ctx = talloc_tos();
5351 const char *sharename = lp_servicename(SNUM(conn));
5352 struct rpc_pipe_client *cli = NULL;
5353 struct dcerpc_binding_handle *b = NULL;
5354 struct policy_handle handle;
5355 struct spoolss_DevmodeContainer devmode_ctr;
5356 union spoolss_JobInfo *info;
5358 uint32_t num_to_get;
5362 ZERO_STRUCT(handle);
5364 status = rpc_pipe_open_interface(conn,
5365 &ndr_table_spoolss.syntax_id,
5367 conn->sconn->remote_address,
5368 conn->sconn->msg_ctx,
5370 if (!NT_STATUS_IS_OK(status)) {
5371 DEBUG(0, ("reply_printqueue: "
5372 "could not connect to spoolss: %s\n",
5373 nt_errstr(status)));
5374 reply_nterror(req, status);
5377 b = cli->binding_handle;
5379 ZERO_STRUCT(devmode_ctr);
5381 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5384 SEC_FLAG_MAXIMUM_ALLOWED,
5387 if (!NT_STATUS_IS_OK(status)) {
5388 reply_nterror(req, status);
5391 if (!W_ERROR_IS_OK(werr)) {
5392 reply_nterror(req, werror_to_ntstatus(werr));
5396 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5404 if (!W_ERROR_IS_OK(werr)) {
5405 reply_nterror(req, werror_to_ntstatus(werr));
5409 if (max_count > 0) {
5410 first = start_index;
5412 first = start_index + max_count + 1;
5415 if (first >= count) {
5418 num_to_get = first + MIN(ABS(max_count), count - first);
5421 for (i = first; i < num_to_get; i++) {
5424 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5426 uint16_t qrapjobid = pjobid_to_rap(sharename,
5427 info[i].info2.job_id);
5429 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5435 srv_put_dos_date2(p, 0, qtime);
5436 SCVAL(p, 4, qstatus);
5437 SSVAL(p, 5, qrapjobid);
5438 SIVAL(p, 7, info[i].info2.size);
5440 srvstr_push(blob, req->flags2, p+12,
5441 info[i].info2.notify_name, 16, STR_ASCII);
5443 if (message_push_blob(
5446 blob, sizeof(blob))) == -1) {
5447 reply_nterror(req, NT_STATUS_NO_MEMORY);
5453 SSVAL(req->outbuf,smb_vwv0,count);
5454 SSVAL(req->outbuf,smb_vwv1,
5455 (max_count>0?first+count:first-1));
5456 SCVAL(smb_buf(req->outbuf),0,1);
5457 SSVAL(smb_buf(req->outbuf),1,28*count);
5461 DEBUG(3, ("%u entries returned in queue\n",
5465 if (b && is_valid_policy_hnd(&handle)) {
5466 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5471 END_PROFILE(SMBsplretq);
5475 /****************************************************************************
5476 Reply to a printwrite.
5477 ****************************************************************************/
5479 void reply_printwrite(struct smb_request *req)
5481 connection_struct *conn = req->conn;
5486 START_PROFILE(SMBsplwr);
5489 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5490 END_PROFILE(SMBsplwr);
5494 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5496 if (!check_fsp(conn, req, fsp)) {
5497 END_PROFILE(SMBsplwr);
5501 if (!fsp->print_file) {
5502 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5503 END_PROFILE(SMBsplwr);
5507 if (!CHECK_WRITE(fsp)) {
5508 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5509 END_PROFILE(SMBsplwr);
5513 numtowrite = SVAL(req->buf, 1);
5515 if (req->buflen < numtowrite + 3) {
5516 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5517 END_PROFILE(SMBsplwr);
5521 data = (const char *)req->buf + 3;
5523 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5524 reply_nterror(req, map_nt_error_from_unix(errno));
5525 END_PROFILE(SMBsplwr);
5529 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5531 END_PROFILE(SMBsplwr);
5535 /****************************************************************************
5537 ****************************************************************************/
5539 void reply_mkdir(struct smb_request *req)
5541 connection_struct *conn = req->conn;
5542 struct smb_filename *smb_dname = NULL;
5543 char *directory = NULL;
5545 TALLOC_CTX *ctx = talloc_tos();
5547 START_PROFILE(SMBmkdir);
5549 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5550 STR_TERMINATE, &status);
5551 if (!NT_STATUS_IS_OK(status)) {
5552 reply_nterror(req, status);
5556 status = filename_convert(ctx, conn,
5557 req->flags2 & FLAGS2_DFS_PATHNAMES,
5562 if (!NT_STATUS_IS_OK(status)) {
5563 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5564 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5565 ERRSRV, ERRbadpath);
5568 reply_nterror(req, status);
5572 status = create_directory(conn, req, smb_dname);
5574 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5576 if (!NT_STATUS_IS_OK(status)) {
5578 if (!use_nt_status()
5579 && NT_STATUS_EQUAL(status,
5580 NT_STATUS_OBJECT_NAME_COLLISION)) {
5582 * Yes, in the DOS error code case we get a
5583 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5584 * samba4 torture test.
5586 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5589 reply_nterror(req, status);
5593 reply_outbuf(req, 0, 0);
5595 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5597 TALLOC_FREE(smb_dname);
5598 END_PROFILE(SMBmkdir);
5602 /****************************************************************************
5604 ****************************************************************************/
5606 void reply_rmdir(struct smb_request *req)
5608 connection_struct *conn = req->conn;
5609 struct smb_filename *smb_dname = NULL;
5610 char *directory = NULL;
5612 TALLOC_CTX *ctx = talloc_tos();
5613 files_struct *fsp = NULL;
5615 struct smbd_server_connection *sconn = req->sconn;
5617 START_PROFILE(SMBrmdir);
5619 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5620 STR_TERMINATE, &status);
5621 if (!NT_STATUS_IS_OK(status)) {
5622 reply_nterror(req, status);
5626 status = filename_convert(ctx, conn,
5627 req->flags2 & FLAGS2_DFS_PATHNAMES,
5632 if (!NT_STATUS_IS_OK(status)) {
5633 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5634 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5635 ERRSRV, ERRbadpath);
5638 reply_nterror(req, status);
5642 if (is_ntfs_stream_smb_fname(smb_dname)) {
5643 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5647 status = SMB_VFS_CREATE_FILE(
5650 0, /* root_dir_fid */
5651 smb_dname, /* fname */
5652 DELETE_ACCESS, /* access_mask */
5653 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5655 FILE_OPEN, /* create_disposition*/
5656 FILE_DIRECTORY_FILE, /* create_options */
5657 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5658 0, /* oplock_request */
5659 0, /* allocation_size */
5660 0, /* private_flags */
5666 if (!NT_STATUS_IS_OK(status)) {
5667 if (open_was_deferred(req->mid)) {
5668 /* We have re-scheduled this call. */
5671 reply_nterror(req, status);
5675 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5676 if (!NT_STATUS_IS_OK(status)) {
5677 close_file(req, fsp, ERROR_CLOSE);
5678 reply_nterror(req, status);
5682 if (!set_delete_on_close(fsp, true, &conn->session_info->utok)) {
5683 close_file(req, fsp, ERROR_CLOSE);
5684 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5688 status = close_file(req, fsp, NORMAL_CLOSE);
5689 if (!NT_STATUS_IS_OK(status)) {
5690 reply_nterror(req, status);
5692 reply_outbuf(req, 0, 0);
5695 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5697 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5699 TALLOC_FREE(smb_dname);
5700 END_PROFILE(SMBrmdir);
5704 /*******************************************************************
5705 Resolve wildcards in a filename rename.
5706 ********************************************************************/
5708 static bool resolve_wildcards(TALLOC_CTX *ctx,
5713 char *name2_copy = NULL;
5718 char *p,*p2, *pname1, *pname2;
5720 name2_copy = talloc_strdup(ctx, name2);
5725 pname1 = strrchr_m(name1,'/');
5726 pname2 = strrchr_m(name2_copy,'/');
5728 if (!pname1 || !pname2) {
5732 /* Truncate the copy of name2 at the last '/' */
5735 /* Now go past the '/' */
5739 root1 = talloc_strdup(ctx, pname1);
5740 root2 = talloc_strdup(ctx, pname2);
5742 if (!root1 || !root2) {
5746 p = strrchr_m(root1,'.');
5749 ext1 = talloc_strdup(ctx, p+1);
5751 ext1 = talloc_strdup(ctx, "");
5753 p = strrchr_m(root2,'.');
5756 ext2 = talloc_strdup(ctx, p+1);
5758 ext2 = talloc_strdup(ctx, "");
5761 if (!ext1 || !ext2) {
5769 /* Hmmm. Should this be mb-aware ? */
5772 } else if (*p2 == '*') {
5774 root2 = talloc_asprintf(ctx, "%s%s",
5793 /* Hmmm. Should this be mb-aware ? */
5796 } else if (*p2 == '*') {
5798 ext2 = talloc_asprintf(ctx, "%s%s",
5814 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5819 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5831 /****************************************************************************
5832 Ensure open files have their names updated. Updated to notify other smbd's
5834 ****************************************************************************/
5836 static void rename_open_files(connection_struct *conn,
5837 struct share_mode_lock *lck,
5838 uint32_t orig_name_hash,
5839 const struct smb_filename *smb_fname_dst)
5842 bool did_rename = False;
5844 uint32_t new_name_hash = 0;
5846 for(fsp = file_find_di_first(conn->sconn, lck->id); fsp;
5847 fsp = file_find_di_next(fsp)) {
5848 /* fsp_name is a relative path under the fsp. To change this for other
5849 sharepaths we need to manipulate relative paths. */
5850 /* TODO - create the absolute path and manipulate the newname
5851 relative to the sharepath. */
5852 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5855 if (fsp->name_hash != orig_name_hash) {
5858 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5859 "(file_id %s) from %s -> %s\n", fsp->fnum,
5860 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5861 smb_fname_str_dbg(smb_fname_dst)));
5863 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5864 if (NT_STATUS_IS_OK(status)) {
5866 new_name_hash = fsp->name_hash;
5871 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5872 "for %s\n", file_id_string_tos(&lck->id),
5873 smb_fname_str_dbg(smb_fname_dst)));
5876 /* Send messages to all smbd's (not ourself) that the name has changed. */
5877 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5878 orig_name_hash, new_name_hash,
5883 /****************************************************************************
5884 We need to check if the source path is a parent directory of the destination
5885 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5886 refuse the rename with a sharing violation. Under UNIX the above call can
5887 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5888 probably need to check that the client is a Windows one before disallowing
5889 this as a UNIX client (one with UNIX extensions) can know the source is a
5890 symlink and make this decision intelligently. Found by an excellent bug
5891 report from <AndyLiebman@aol.com>.
5892 ****************************************************************************/
5894 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5895 const struct smb_filename *smb_fname_dst)
5897 const char *psrc = smb_fname_src->base_name;
5898 const char *pdst = smb_fname_dst->base_name;
5901 if (psrc[0] == '.' && psrc[1] == '/') {
5904 if (pdst[0] == '.' && pdst[1] == '/') {
5907 if ((slen = strlen(psrc)) > strlen(pdst)) {
5910 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5914 * Do the notify calls from a rename
5917 static void notify_rename(connection_struct *conn, bool is_dir,
5918 const struct smb_filename *smb_fname_src,
5919 const struct smb_filename *smb_fname_dst)
5921 char *parent_dir_src = NULL;
5922 char *parent_dir_dst = NULL;
5925 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5926 : FILE_NOTIFY_CHANGE_FILE_NAME;
5928 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5929 &parent_dir_src, NULL) ||
5930 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5931 &parent_dir_dst, NULL)) {
5935 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5936 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5937 smb_fname_src->base_name);
5938 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5939 smb_fname_dst->base_name);
5942 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5943 smb_fname_src->base_name);
5944 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5945 smb_fname_dst->base_name);
5948 /* this is a strange one. w2k3 gives an additional event for
5949 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5950 files, but not directories */
5952 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5953 FILE_NOTIFY_CHANGE_ATTRIBUTES
5954 |FILE_NOTIFY_CHANGE_CREATION,
5955 smb_fname_dst->base_name);
5958 TALLOC_FREE(parent_dir_src);
5959 TALLOC_FREE(parent_dir_dst);
5962 /****************************************************************************
5963 Rename an open file - given an fsp.
5964 ****************************************************************************/
5966 NTSTATUS rename_internals_fsp(connection_struct *conn,
5968 const struct smb_filename *smb_fname_dst_in,
5970 bool replace_if_exists)
5972 TALLOC_CTX *ctx = talloc_tos();
5973 struct smb_filename *smb_fname_dst = NULL;
5974 NTSTATUS status = NT_STATUS_OK;
5975 struct share_mode_lock *lck = NULL;
5976 bool dst_exists, old_is_stream, new_is_stream;
5978 status = check_name(conn, smb_fname_dst_in->base_name);
5979 if (!NT_STATUS_IS_OK(status)) {
5983 /* Make a copy of the dst smb_fname structs */
5985 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5986 if (!NT_STATUS_IS_OK(status)) {
5991 * Check for special case with case preserving and not
5992 * case sensitive. If the old last component differs from the original
5993 * last component only by case, then we should allow
5994 * the rename (user is trying to change the case of the
5997 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5998 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5999 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6001 char *fname_dst_lcomp_base_mod = NULL;
6002 struct smb_filename *smb_fname_orig_lcomp = NULL;
6005 * Get the last component of the destination name.
6007 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6009 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6011 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6013 if (!fname_dst_lcomp_base_mod) {
6014 status = NT_STATUS_NO_MEMORY;
6019 * Create an smb_filename struct using the original last
6020 * component of the destination.
6022 status = create_synthetic_smb_fname_split(ctx,
6023 smb_fname_dst->original_lcomp, NULL,
6024 &smb_fname_orig_lcomp);
6025 if (!NT_STATUS_IS_OK(status)) {
6026 TALLOC_FREE(fname_dst_lcomp_base_mod);
6030 /* If the base names only differ by case, use original. */
6031 if(!strcsequal(fname_dst_lcomp_base_mod,
6032 smb_fname_orig_lcomp->base_name)) {
6035 * Replace the modified last component with the
6039 *last_slash = '\0'; /* Truncate at the '/' */
6040 tmp = talloc_asprintf(smb_fname_dst,
6042 smb_fname_dst->base_name,
6043 smb_fname_orig_lcomp->base_name);
6045 tmp = talloc_asprintf(smb_fname_dst,
6047 smb_fname_orig_lcomp->base_name);
6050 status = NT_STATUS_NO_MEMORY;
6051 TALLOC_FREE(fname_dst_lcomp_base_mod);
6052 TALLOC_FREE(smb_fname_orig_lcomp);
6055 TALLOC_FREE(smb_fname_dst->base_name);
6056 smb_fname_dst->base_name = tmp;
6059 /* If the stream_names only differ by case, use original. */
6060 if(!strcsequal(smb_fname_dst->stream_name,
6061 smb_fname_orig_lcomp->stream_name)) {
6063 /* Use the original stream. */
6064 tmp = talloc_strdup(smb_fname_dst,
6065 smb_fname_orig_lcomp->stream_name);
6067 status = NT_STATUS_NO_MEMORY;
6068 TALLOC_FREE(fname_dst_lcomp_base_mod);
6069 TALLOC_FREE(smb_fname_orig_lcomp);
6072 TALLOC_FREE(smb_fname_dst->stream_name);
6073 smb_fname_dst->stream_name = tmp;
6075 TALLOC_FREE(fname_dst_lcomp_base_mod);
6076 TALLOC_FREE(smb_fname_orig_lcomp);
6080 * If the src and dest names are identical - including case,
6081 * don't do the rename, just return success.
6084 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6085 strcsequal(fsp->fsp_name->stream_name,
6086 smb_fname_dst->stream_name)) {
6087 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6088 "- returning success\n",
6089 smb_fname_str_dbg(smb_fname_dst)));
6090 status = NT_STATUS_OK;
6094 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6095 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6097 /* Return the correct error code if both names aren't streams. */
6098 if (!old_is_stream && new_is_stream) {
6099 status = NT_STATUS_OBJECT_NAME_INVALID;
6103 if (old_is_stream && !new_is_stream) {
6104 status = NT_STATUS_INVALID_PARAMETER;
6108 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6110 if(!replace_if_exists && dst_exists) {
6111 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6112 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6113 smb_fname_str_dbg(smb_fname_dst)));
6114 status = NT_STATUS_OBJECT_NAME_COLLISION;
6119 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6120 &smb_fname_dst->st);
6121 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6123 /* The file can be open when renaming a stream */
6124 if (dst_fsp && !new_is_stream) {
6125 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6126 status = NT_STATUS_ACCESS_DENIED;
6131 /* Ensure we have a valid stat struct for the source. */
6132 status = vfs_stat_fsp(fsp);
6133 if (!NT_STATUS_IS_OK(status)) {
6137 status = can_rename(conn, fsp, attrs);
6139 if (!NT_STATUS_IS_OK(status)) {
6140 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6141 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6142 smb_fname_str_dbg(smb_fname_dst)));
6143 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6144 status = NT_STATUS_ACCESS_DENIED;
6148 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6149 status = NT_STATUS_ACCESS_DENIED;
6152 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6156 * We have the file open ourselves, so not being able to get the
6157 * corresponding share mode lock is a fatal error.
6160 SMB_ASSERT(lck != NULL);
6162 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6163 uint32 create_options = fsp->fh->private_options;
6165 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6166 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6167 smb_fname_str_dbg(smb_fname_dst)));
6169 if (!lp_posix_pathnames() &&
6170 (lp_map_archive(SNUM(conn)) ||
6171 lp_store_dos_attributes(SNUM(conn)))) {
6172 /* We must set the archive bit on the newly
6174 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6175 uint32_t old_dosmode = dos_mode(conn,
6177 file_set_dosmode(conn,
6179 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6185 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6188 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6191 * A rename acts as a new file create w.r.t. allowing an initial delete
6192 * on close, probably because in Windows there is a new handle to the
6193 * new file. If initial delete on close was requested but not
6194 * originally set, we need to set it here. This is probably not 100% correct,
6195 * but will work for the CIFSFS client which in non-posix mode
6196 * depends on these semantics. JRA.
6199 if (create_options & FILE_DELETE_ON_CLOSE) {
6200 status = can_set_delete_on_close(fsp, 0);
6202 if (NT_STATUS_IS_OK(status)) {
6203 /* Note that here we set the *inital* delete on close flag,
6204 * not the regular one. The magic gets handled in close. */
6205 fsp->initial_delete_on_close = True;
6209 status = NT_STATUS_OK;
6215 if (errno == ENOTDIR || errno == EISDIR) {
6216 status = NT_STATUS_OBJECT_NAME_COLLISION;
6218 status = map_nt_error_from_unix(errno);
6221 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6222 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6223 smb_fname_str_dbg(smb_fname_dst)));
6226 TALLOC_FREE(smb_fname_dst);
6231 /****************************************************************************
6232 The guts of the rename command, split out so it may be called by the NT SMB
6234 ****************************************************************************/
6236 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6237 connection_struct *conn,
6238 struct smb_request *req,
6239 struct smb_filename *smb_fname_src,
6240 struct smb_filename *smb_fname_dst,
6242 bool replace_if_exists,
6245 uint32_t access_mask)
6247 char *fname_src_dir = NULL;
6248 char *fname_src_mask = NULL;
6250 NTSTATUS status = NT_STATUS_OK;
6251 struct smb_Dir *dir_hnd = NULL;
6252 const char *dname = NULL;
6253 char *talloced = NULL;
6255 int create_options = 0;
6256 bool posix_pathnames = lp_posix_pathnames();
6259 * Split the old name into directory and last component
6260 * strings. Note that unix_convert may have stripped off a
6261 * leading ./ from both name and newname if the rename is
6262 * at the root of the share. We need to make sure either both
6263 * name and newname contain a / character or neither of them do
6264 * as this is checked in resolve_wildcards().
6267 /* Split up the directory from the filename/mask. */
6268 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6269 &fname_src_dir, &fname_src_mask);
6270 if (!NT_STATUS_IS_OK(status)) {
6271 status = NT_STATUS_NO_MEMORY;
6276 * We should only check the mangled cache
6277 * here if unix_convert failed. This means
6278 * that the path in 'mask' doesn't exist
6279 * on the file system and so we need to look
6280 * for a possible mangle. This patch from
6281 * Tine Smukavec <valentin.smukavec@hermes.si>.
6284 if (!VALID_STAT(smb_fname_src->st) &&
6285 mangle_is_mangled(fname_src_mask, conn->params)) {
6286 char *new_mask = NULL;
6287 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6290 TALLOC_FREE(fname_src_mask);
6291 fname_src_mask = new_mask;
6295 if (!src_has_wild) {
6299 * Only one file needs to be renamed. Append the mask back
6300 * onto the directory.
6302 TALLOC_FREE(smb_fname_src->base_name);
6303 if (ISDOT(fname_src_dir)) {
6304 /* Ensure we use canonical names on open. */
6305 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6309 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6314 if (!smb_fname_src->base_name) {
6315 status = NT_STATUS_NO_MEMORY;
6319 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6320 "case_preserve = %d, short case preserve = %d, "
6321 "directory = %s, newname = %s, "
6322 "last_component_dest = %s\n",
6323 conn->case_sensitive, conn->case_preserve,
6324 conn->short_case_preserve,
6325 smb_fname_str_dbg(smb_fname_src),
6326 smb_fname_str_dbg(smb_fname_dst),
6327 smb_fname_dst->original_lcomp));
6329 /* The dest name still may have wildcards. */
6330 if (dest_has_wild) {
6331 char *fname_dst_mod = NULL;
6332 if (!resolve_wildcards(smb_fname_dst,
6333 smb_fname_src->base_name,
6334 smb_fname_dst->base_name,
6336 DEBUG(6, ("rename_internals: resolve_wildcards "
6338 smb_fname_src->base_name,
6339 smb_fname_dst->base_name));
6340 status = NT_STATUS_NO_MEMORY;
6343 TALLOC_FREE(smb_fname_dst->base_name);
6344 smb_fname_dst->base_name = fname_dst_mod;
6347 ZERO_STRUCT(smb_fname_src->st);
6348 if (posix_pathnames) {
6349 SMB_VFS_LSTAT(conn, smb_fname_src);
6351 SMB_VFS_STAT(conn, smb_fname_src);
6354 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6355 create_options |= FILE_DIRECTORY_FILE;
6358 status = SMB_VFS_CREATE_FILE(
6361 0, /* root_dir_fid */
6362 smb_fname_src, /* fname */
6363 access_mask, /* access_mask */
6364 (FILE_SHARE_READ | /* share_access */
6366 FILE_OPEN, /* create_disposition*/
6367 create_options, /* create_options */
6368 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6369 0, /* oplock_request */
6370 0, /* allocation_size */
6371 0, /* private_flags */
6377 if (!NT_STATUS_IS_OK(status)) {
6378 DEBUG(3, ("Could not open rename source %s: %s\n",
6379 smb_fname_str_dbg(smb_fname_src),
6380 nt_errstr(status)));
6384 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6385 attrs, replace_if_exists);
6387 close_file(req, fsp, NORMAL_CLOSE);
6389 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6390 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6391 smb_fname_str_dbg(smb_fname_dst)));
6397 * Wildcards - process each file that matches.
6399 if (strequal(fname_src_mask, "????????.???")) {
6400 TALLOC_FREE(fname_src_mask);
6401 fname_src_mask = talloc_strdup(ctx, "*");
6402 if (!fname_src_mask) {
6403 status = NT_STATUS_NO_MEMORY;
6408 status = check_name(conn, fname_src_dir);
6409 if (!NT_STATUS_IS_OK(status)) {
6413 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6415 if (dir_hnd == NULL) {
6416 status = map_nt_error_from_unix(errno);
6420 status = NT_STATUS_NO_SUCH_FILE;
6422 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6423 * - gentest fix. JRA
6426 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6428 files_struct *fsp = NULL;
6429 char *destname = NULL;
6430 bool sysdir_entry = False;
6432 /* Quick check for "." and ".." */
6433 if (ISDOT(dname) || ISDOTDOT(dname)) {
6434 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6435 sysdir_entry = True;
6437 TALLOC_FREE(talloced);
6442 if (!is_visible_file(conn, fname_src_dir, dname,
6443 &smb_fname_src->st, false)) {
6444 TALLOC_FREE(talloced);
6448 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6449 TALLOC_FREE(talloced);
6454 status = NT_STATUS_OBJECT_NAME_INVALID;
6458 TALLOC_FREE(smb_fname_src->base_name);
6459 if (ISDOT(fname_src_dir)) {
6460 /* Ensure we use canonical names on open. */
6461 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6465 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6470 if (!smb_fname_src->base_name) {
6471 status = NT_STATUS_NO_MEMORY;
6475 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6476 smb_fname_dst->base_name,
6478 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6479 smb_fname_src->base_name, destname));
6480 TALLOC_FREE(talloced);
6484 status = NT_STATUS_NO_MEMORY;
6488 TALLOC_FREE(smb_fname_dst->base_name);
6489 smb_fname_dst->base_name = destname;
6491 ZERO_STRUCT(smb_fname_src->st);
6492 if (posix_pathnames) {
6493 SMB_VFS_LSTAT(conn, smb_fname_src);
6495 SMB_VFS_STAT(conn, smb_fname_src);
6500 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6501 create_options |= FILE_DIRECTORY_FILE;
6504 status = SMB_VFS_CREATE_FILE(
6507 0, /* root_dir_fid */
6508 smb_fname_src, /* fname */
6509 access_mask, /* access_mask */
6510 (FILE_SHARE_READ | /* share_access */
6512 FILE_OPEN, /* create_disposition*/
6513 create_options, /* create_options */
6514 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6515 0, /* oplock_request */
6516 0, /* allocation_size */
6517 0, /* private_flags */
6523 if (!NT_STATUS_IS_OK(status)) {
6524 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6525 "returned %s rename %s -> %s\n",
6527 smb_fname_str_dbg(smb_fname_src),
6528 smb_fname_str_dbg(smb_fname_dst)));
6532 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6534 if (!smb_fname_dst->original_lcomp) {
6535 status = NT_STATUS_NO_MEMORY;
6539 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6540 attrs, replace_if_exists);
6542 close_file(req, fsp, NORMAL_CLOSE);
6544 if (!NT_STATUS_IS_OK(status)) {
6545 DEBUG(3, ("rename_internals_fsp returned %s for "
6546 "rename %s -> %s\n", nt_errstr(status),
6547 smb_fname_str_dbg(smb_fname_src),
6548 smb_fname_str_dbg(smb_fname_dst)));
6554 DEBUG(3,("rename_internals: doing rename on %s -> "
6555 "%s\n", smb_fname_str_dbg(smb_fname_src),
6556 smb_fname_str_dbg(smb_fname_src)));
6557 TALLOC_FREE(talloced);
6559 TALLOC_FREE(dir_hnd);
6561 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6562 status = map_nt_error_from_unix(errno);
6566 TALLOC_FREE(talloced);
6567 TALLOC_FREE(fname_src_dir);
6568 TALLOC_FREE(fname_src_mask);
6572 /****************************************************************************
6574 ****************************************************************************/
6576 void reply_mv(struct smb_request *req)
6578 connection_struct *conn = req->conn;
6580 char *newname = NULL;
6584 bool src_has_wcard = False;
6585 bool dest_has_wcard = False;
6586 TALLOC_CTX *ctx = talloc_tos();
6587 struct smb_filename *smb_fname_src = NULL;
6588 struct smb_filename *smb_fname_dst = NULL;
6589 bool stream_rename = false;
6591 START_PROFILE(SMBmv);
6594 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6598 attrs = SVAL(req->vwv+0, 0);
6600 p = (const char *)req->buf + 1;
6601 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6602 &status, &src_has_wcard);
6603 if (!NT_STATUS_IS_OK(status)) {
6604 reply_nterror(req, status);
6608 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6609 &status, &dest_has_wcard);
6610 if (!NT_STATUS_IS_OK(status)) {
6611 reply_nterror(req, status);
6615 if (!lp_posix_pathnames()) {
6616 /* The newname must begin with a ':' if the
6617 name contains a ':'. */
6618 if (strchr_m(name, ':')) {
6619 if (newname[0] != ':') {
6620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6623 stream_rename = true;
6627 status = filename_convert(ctx,
6629 req->flags2 & FLAGS2_DFS_PATHNAMES,
6631 UCF_COND_ALLOW_WCARD_LCOMP,
6635 if (!NT_STATUS_IS_OK(status)) {
6636 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6637 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6638 ERRSRV, ERRbadpath);
6641 reply_nterror(req, status);
6645 status = filename_convert(ctx,
6647 req->flags2 & FLAGS2_DFS_PATHNAMES,
6649 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6653 if (!NT_STATUS_IS_OK(status)) {
6654 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6655 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6656 ERRSRV, ERRbadpath);
6659 reply_nterror(req, status);
6663 if (stream_rename) {
6664 /* smb_fname_dst->base_name must be the same as
6665 smb_fname_src->base_name. */
6666 TALLOC_FREE(smb_fname_dst->base_name);
6667 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6668 smb_fname_src->base_name);
6669 if (!smb_fname_dst->base_name) {
6670 reply_nterror(req, NT_STATUS_NO_MEMORY);
6675 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6676 smb_fname_str_dbg(smb_fname_dst)));
6678 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6679 attrs, False, src_has_wcard, dest_has_wcard,
6681 if (!NT_STATUS_IS_OK(status)) {
6682 if (open_was_deferred(req->mid)) {
6683 /* We have re-scheduled this call. */
6686 reply_nterror(req, status);
6690 reply_outbuf(req, 0, 0);
6692 TALLOC_FREE(smb_fname_src);
6693 TALLOC_FREE(smb_fname_dst);
6698 /*******************************************************************
6699 Copy a file as part of a reply_copy.
6700 ******************************************************************/
6703 * TODO: check error codes on all callers
6706 NTSTATUS copy_file(TALLOC_CTX *ctx,
6707 connection_struct *conn,
6708 struct smb_filename *smb_fname_src,
6709 struct smb_filename *smb_fname_dst,
6712 bool target_is_directory)
6714 struct smb_filename *smb_fname_dst_tmp = NULL;
6716 files_struct *fsp1,*fsp2;
6718 uint32 new_create_disposition;
6722 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6723 if (!NT_STATUS_IS_OK(status)) {
6728 * If the target is a directory, extract the last component from the
6729 * src filename and append it to the dst filename
6731 if (target_is_directory) {
6734 /* dest/target can't be a stream if it's a directory. */
6735 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6737 p = strrchr_m(smb_fname_src->base_name,'/');
6741 p = smb_fname_src->base_name;
6743 smb_fname_dst_tmp->base_name =
6744 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6746 if (!smb_fname_dst_tmp->base_name) {
6747 status = NT_STATUS_NO_MEMORY;
6752 status = vfs_file_exist(conn, smb_fname_src);
6753 if (!NT_STATUS_IS_OK(status)) {
6757 if (!target_is_directory && count) {
6758 new_create_disposition = FILE_OPEN;
6760 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
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);