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 "smbd/globals.h"
30 extern enum protocol_types Protocol;
32 /****************************************************************************
33 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
34 path or anything including wildcards.
35 We're assuming here that '/' is not the second byte in any multibyte char
36 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
38 ****************************************************************************/
40 /* Custom version for processing POSIX paths. */
41 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
43 static NTSTATUS check_path_syntax_internal(char *path,
45 bool *p_last_component_contains_wcard)
49 NTSTATUS ret = NT_STATUS_OK;
50 bool start_of_name_component = True;
51 bool stream_started = false;
53 *p_last_component_contains_wcard = False;
60 return NT_STATUS_OBJECT_NAME_INVALID;
63 return NT_STATUS_OBJECT_NAME_INVALID;
65 if (strchr_m(&s[1], ':')) {
66 return NT_STATUS_OBJECT_NAME_INVALID;
68 if (StrCaseCmp(s, ":$DATA") != 0) {
69 return NT_STATUS_INVALID_PARAMETER;
75 if (!posix_path && !stream_started && *s == ':') {
76 if (*p_last_component_contains_wcard) {
77 return NT_STATUS_OBJECT_NAME_INVALID;
79 /* Stream names allow more characters than file names.
80 We're overloading posix_path here to allow a wider
81 range of characters. If stream_started is true this
82 is still a Windows path even if posix_path is true.
85 stream_started = true;
86 start_of_name_component = false;
90 return NT_STATUS_OBJECT_NAME_INVALID;
94 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
96 * Safe to assume is not the second part of a mb char
97 * as this is handled below.
99 /* Eat multiple '/' or '\\' */
100 while (IS_PATH_SEP(*s,posix_path)) {
103 if ((d != path) && (*s != '\0')) {
104 /* We only care about non-leading or trailing '/' or '\\' */
108 start_of_name_component = True;
110 *p_last_component_contains_wcard = False;
114 if (start_of_name_component) {
115 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
116 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
119 * No mb char starts with '.' so we're safe checking the directory separator here.
122 /* If we just added a '/' - delete it */
123 if ((d > path) && (*(d-1) == '/')) {
128 /* Are we at the start ? Can't go back further if so. */
130 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
133 /* Go back one level... */
134 /* We know this is safe as '/' cannot be part of a mb sequence. */
135 /* NOTE - if this assumption is invalid we are not in good shape... */
136 /* Decrement d first as d points to the *next* char to write into. */
137 for (d--; d > path; d--) {
141 s += 2; /* Else go past the .. */
142 /* We're still at the start of a name component, just the previous one. */
145 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
157 if (*s <= 0x1f || *s == '|') {
158 return NT_STATUS_OBJECT_NAME_INVALID;
166 *p_last_component_contains_wcard = True;
175 /* Get the size of the next MB character. */
176 next_codepoint(s,&siz);
194 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
196 return NT_STATUS_INVALID_PARAMETER;
199 start_of_name_component = False;
207 /****************************************************************************
208 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
209 No wildcards allowed.
210 ****************************************************************************/
212 NTSTATUS check_path_syntax(char *path)
215 return check_path_syntax_internal(path, False, &ignore);
218 /****************************************************************************
219 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
220 Wildcards allowed - p_contains_wcard returns true if the last component contained
222 ****************************************************************************/
224 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
226 return check_path_syntax_internal(path, False, p_contains_wcard);
229 /****************************************************************************
230 Check the path for a POSIX client.
231 We're assuming here that '/' is not the second byte in any multibyte char
232 set (a safe assumption).
233 ****************************************************************************/
235 NTSTATUS check_path_syntax_posix(char *path)
238 return check_path_syntax_internal(path, True, &ignore);
241 /****************************************************************************
242 Pull a string and check the path allowing a wilcard - provide for error return.
243 ****************************************************************************/
245 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
246 const char *base_ptr,
253 bool *contains_wcard)
259 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
263 *err = NT_STATUS_INVALID_PARAMETER;
267 *contains_wcard = False;
269 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
271 * For a DFS path the function parse_dfs_path()
272 * will do the path processing, just make a copy.
278 if (lp_posix_pathnames()) {
279 *err = check_path_syntax_posix(*pp_dest);
281 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
287 /****************************************************************************
288 Pull a string and check the path - provide for error return.
289 ****************************************************************************/
291 size_t srvstr_get_path(TALLOC_CTX *ctx,
292 const char *base_ptr,
301 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
302 src_len, flags, err, &ignore);
305 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
306 char **pp_dest, const char *src, int flags,
307 NTSTATUS *err, bool *contains_wcard)
309 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
310 pp_dest, src, smbreq_bufrem(req, src),
311 flags, err, contains_wcard);
314 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
315 char **pp_dest, const char *src, int flags,
319 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
320 flags, err, &ignore);
323 /****************************************************************************
324 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
325 ****************************************************************************/
327 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
330 if (!(fsp) || !(conn)) {
331 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
334 if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
335 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
341 /****************************************************************************
342 Check if we have a correct fsp pointing to a file.
343 ****************************************************************************/
345 bool check_fsp(connection_struct *conn, struct smb_request *req,
348 if (!check_fsp_open(conn, req, fsp)) {
351 if ((fsp)->is_directory) {
352 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
355 if ((fsp)->fh->fd == -1) {
356 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
359 (fsp)->num_smb_operations++;
363 /****************************************************************************
364 Check if we have a correct fsp pointing to a quota fake file. Replacement for
365 the CHECK_NTQUOTA_HANDLE_OK macro.
366 ****************************************************************************/
368 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
371 if (!check_fsp_open(conn, req, fsp)) {
375 if (fsp->is_directory) {
379 if (fsp->fake_file_handle == NULL) {
383 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
387 if (fsp->fake_file_handle->private_data == NULL) {
394 /****************************************************************************
395 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
396 ****************************************************************************/
398 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
401 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
402 && (req->vuid == (fsp)->vuid)) {
406 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
410 static bool netbios_session_retarget(const char *name, int name_type)
413 char *trim_name_type;
414 const char *retarget_parm;
417 int retarget_type = 0x20;
418 int retarget_port = 139;
419 struct sockaddr_storage retarget_addr;
420 struct sockaddr_in *in_addr;
424 if (get_socket_port(smbd_server_fd()) != 139) {
428 trim_name = talloc_strdup(talloc_tos(), name);
429 if (trim_name == NULL) {
432 trim_char(trim_name, ' ', ' ');
434 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
436 if (trim_name_type == NULL) {
440 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
441 trim_name_type, NULL);
442 if (retarget_parm == NULL) {
443 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
446 if (retarget_parm == NULL) {
450 retarget = talloc_strdup(trim_name, retarget_parm);
451 if (retarget == NULL) {
455 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
457 p = strchr(retarget, ':');
460 retarget_port = atoi(p);
463 p = strchr_m(retarget, '#');
466 sscanf(p, "%x", &retarget_type);
469 ret = resolve_name(retarget, &retarget_addr, retarget_type);
471 DEBUG(10, ("could not resolve %s\n", retarget));
475 if (retarget_addr.ss_family != AF_INET) {
476 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
480 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
482 _smb_setlen(outbuf, 6);
483 SCVAL(outbuf, 0, 0x84);
484 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
485 *(uint16_t *)(outbuf+8) = htons(retarget_port);
487 if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
489 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
495 TALLOC_FREE(trim_name);
499 /****************************************************************************
500 Reply to a (netbios-level) special message.
501 ****************************************************************************/
503 void reply_special(char *inbuf)
505 int msg_type = CVAL(inbuf,0);
506 int msg_flags = CVAL(inbuf,1);
508 char name_type1, name_type2;
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];
519 memset(outbuf, '\0', sizeof(outbuf));
521 smb_setlen(outbuf,0);
524 case 0x81: /* session request */
526 if (already_got_session) {
527 exit_server_cleanly("multiple session request not permitted");
530 SCVAL(outbuf,0,0x82);
532 if (name_len(inbuf+4) > 50 ||
533 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
534 DEBUG(0,("Invalid name length in session request\n"));
537 name_type1 = name_extract(inbuf,4,name1);
538 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
539 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
540 name1, name_type1, name2, name_type2));
542 if (netbios_session_retarget(name1, name_type1)) {
543 exit_server_cleanly("retargeted client");
546 set_local_machine_name(name1, True);
547 set_remote_machine_name(name2, True);
549 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
550 get_local_machine_name(), get_remote_machine_name(),
553 if (name_type2 == 'R') {
554 /* We are being asked for a pathworks session ---
556 SCVAL(outbuf, 0,0x83);
560 /* only add the client's machine name to the list
561 of possibly valid usernames if we are operating
562 in share mode security */
563 if (lp_security() == SEC_SHARE) {
564 add_session_user(get_remote_machine_name());
567 reload_services(True);
570 already_got_session = True;
573 case 0x89: /* session keepalive request
574 (some old clients produce this?) */
575 SCVAL(outbuf,0,SMBkeepalive);
579 case 0x82: /* positive session response */
580 case 0x83: /* negative session response */
581 case 0x84: /* retarget session response */
582 DEBUG(0,("Unexpected session response\n"));
585 case SMBkeepalive: /* session keepalive */
590 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
591 msg_type, msg_flags));
593 srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
597 /****************************************************************************
599 conn POINTER CAN BE NULL HERE !
600 ****************************************************************************/
602 void reply_tcon(struct smb_request *req)
604 connection_struct *conn = req->conn;
606 char *service_buf = NULL;
607 char *password = NULL;
612 DATA_BLOB password_blob;
613 TALLOC_CTX *ctx = talloc_tos();
615 START_PROFILE(SMBtcon);
617 if (req->buflen < 4) {
618 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
619 END_PROFILE(SMBtcon);
623 p = (const char *)req->buf + 1;
624 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
626 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
628 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
631 if (service_buf == NULL || password == NULL || dev == NULL) {
632 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
633 END_PROFILE(SMBtcon);
636 p = strrchr_m(service_buf,'\\');
640 service = service_buf;
643 password_blob = data_blob(password, pwlen+1);
645 conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
648 data_blob_clear_free(&password_blob);
651 reply_nterror(req, nt_status);
652 END_PROFILE(SMBtcon);
656 reply_outbuf(req, 2, 0);
657 SSVAL(req->outbuf,smb_vwv0,max_recv);
658 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
659 SSVAL(req->outbuf,smb_tid,conn->cnum);
661 DEBUG(3,("tcon service=%s cnum=%d\n",
662 service, conn->cnum));
664 END_PROFILE(SMBtcon);
668 /****************************************************************************
669 Reply to a tcon and X.
670 conn POINTER CAN BE NULL HERE !
671 ****************************************************************************/
673 void reply_tcon_and_X(struct smb_request *req)
675 connection_struct *conn = req->conn;
676 const char *service = NULL;
678 TALLOC_CTX *ctx = talloc_tos();
679 /* what the cleint thinks the device is */
680 char *client_devicetype = NULL;
681 /* what the server tells the client the share represents */
682 const char *server_devicetype;
688 struct smbd_server_connection *sconn = smbd_server_conn;
690 START_PROFILE(SMBtconX);
693 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
694 END_PROFILE(SMBtconX);
698 passlen = SVAL(req->vwv+3, 0);
699 tcon_flags = SVAL(req->vwv+2, 0);
701 /* we might have to close an old one */
702 if ((tcon_flags & 0x1) && conn) {
703 close_cnum(conn,req->vuid);
708 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
709 reply_doserror(req, ERRDOS, ERRbuftoosmall);
710 END_PROFILE(SMBtconX);
714 if (sconn->smb1.negprot.encrypted_passwords) {
715 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
716 if (lp_security() == SEC_SHARE) {
718 * Security = share always has a pad byte
719 * after the password.
721 p = (const char *)req->buf + passlen + 1;
723 p = (const char *)req->buf + passlen;
726 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
727 /* Ensure correct termination */
728 password.data[passlen]=0;
729 p = (const char *)req->buf + passlen + 1;
732 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
735 data_blob_clear_free(&password);
736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
737 END_PROFILE(SMBtconX);
742 * the service name can be either: \\server\share
743 * or share directly like on the DELL PowerVault 705
746 q = strchr_m(path+2,'\\');
748 data_blob_clear_free(&password);
749 reply_doserror(req, ERRDOS, ERRnosuchshare);
750 END_PROFILE(SMBtconX);
758 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
759 &client_devicetype, p,
760 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
762 if (client_devicetype == NULL) {
763 data_blob_clear_free(&password);
764 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
765 END_PROFILE(SMBtconX);
769 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
771 conn = make_connection(service, password, client_devicetype,
772 req->vuid, &nt_status);
775 data_blob_clear_free(&password);
778 reply_nterror(req, nt_status);
779 END_PROFILE(SMBtconX);
784 server_devicetype = "IPC";
785 else if ( IS_PRINT(conn) )
786 server_devicetype = "LPT1:";
788 server_devicetype = "A:";
790 if (Protocol < PROTOCOL_NT1) {
791 reply_outbuf(req, 2, 0);
792 if (message_push_string(&req->outbuf, server_devicetype,
793 STR_TERMINATE|STR_ASCII) == -1) {
794 reply_nterror(req, NT_STATUS_NO_MEMORY);
795 END_PROFILE(SMBtconX);
799 /* NT sets the fstype of IPC$ to the null string */
800 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
802 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
803 /* Return permissions. */
807 reply_outbuf(req, 7, 0);
810 perm1 = FILE_ALL_ACCESS;
811 perm2 = FILE_ALL_ACCESS;
813 perm1 = CAN_WRITE(conn) ?
818 SIVAL(req->outbuf, smb_vwv3, perm1);
819 SIVAL(req->outbuf, smb_vwv5, perm2);
821 reply_outbuf(req, 3, 0);
824 if ((message_push_string(&req->outbuf, server_devicetype,
825 STR_TERMINATE|STR_ASCII) == -1)
826 || (message_push_string(&req->outbuf, fstype,
827 STR_TERMINATE) == -1)) {
828 reply_nterror(req, NT_STATUS_NO_MEMORY);
829 END_PROFILE(SMBtconX);
833 /* what does setting this bit do? It is set by NT4 and
834 may affect the ability to autorun mounted cdroms */
835 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
836 (lp_csc_policy(SNUM(conn)) << 2));
838 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
839 DEBUG(2,("Serving %s as a Dfs root\n",
840 lp_servicename(SNUM(conn)) ));
841 SSVAL(req->outbuf, smb_vwv2,
842 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
847 DEBUG(3,("tconX service=%s \n",
850 /* set the incoming and outgoing tid to the just created one */
851 SSVAL(req->inbuf,smb_tid,conn->cnum);
852 SSVAL(req->outbuf,smb_tid,conn->cnum);
854 END_PROFILE(SMBtconX);
860 /****************************************************************************
861 Reply to an unknown type.
862 ****************************************************************************/
864 void reply_unknown_new(struct smb_request *req, uint8 type)
866 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
867 smb_fn_name(type), type, type));
868 reply_doserror(req, ERRSRV, ERRunknownsmb);
872 /****************************************************************************
874 conn POINTER CAN BE NULL HERE !
875 ****************************************************************************/
877 void reply_ioctl(struct smb_request *req)
879 connection_struct *conn = req->conn;
886 START_PROFILE(SMBioctl);
889 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
890 END_PROFILE(SMBioctl);
894 device = SVAL(req->vwv+1, 0);
895 function = SVAL(req->vwv+2, 0);
896 ioctl_code = (device << 16) + function;
898 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
900 switch (ioctl_code) {
901 case IOCTL_QUERY_JOB_INFO:
905 reply_doserror(req, ERRSRV, ERRnosupport);
906 END_PROFILE(SMBioctl);
910 reply_outbuf(req, 8, replysize+1);
911 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
912 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
913 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
914 p = smb_buf(req->outbuf);
915 memset(p, '\0', replysize+1); /* valgrind-safe. */
916 p += 1; /* Allow for alignment */
918 switch (ioctl_code) {
919 case IOCTL_QUERY_JOB_INFO:
921 files_struct *fsp = file_fsp(
922 req, SVAL(req->vwv+0, 0));
924 reply_doserror(req, ERRDOS, ERRbadfid);
925 END_PROFILE(SMBioctl);
928 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
929 srvstr_push((char *)req->outbuf, req->flags2, p+2,
931 STR_TERMINATE|STR_ASCII);
933 srvstr_push((char *)req->outbuf, req->flags2,
934 p+18, lp_servicename(SNUM(conn)),
935 13, STR_TERMINATE|STR_ASCII);
943 END_PROFILE(SMBioctl);
947 /****************************************************************************
948 Strange checkpath NTSTATUS mapping.
949 ****************************************************************************/
951 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
953 /* Strange DOS error code semantics only for checkpath... */
954 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
955 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
956 /* We need to map to ERRbadpath */
957 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
963 /****************************************************************************
964 Reply to a checkpath.
965 ****************************************************************************/
967 void reply_checkpath(struct smb_request *req)
969 connection_struct *conn = req->conn;
970 struct smb_filename *smb_fname = NULL;
973 TALLOC_CTX *ctx = talloc_tos();
975 START_PROFILE(SMBcheckpath);
977 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
978 STR_TERMINATE, &status);
980 if (!NT_STATUS_IS_OK(status)) {
981 status = map_checkpath_error(req->flags2, status);
982 reply_nterror(req, status);
983 END_PROFILE(SMBcheckpath);
987 status = resolve_dfspath(ctx, conn,
988 req->flags2 & FLAGS2_DFS_PATHNAMES,
991 if (!NT_STATUS_IS_OK(status)) {
992 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
993 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
995 END_PROFILE(SMBcheckpath);
1001 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1003 status = unix_convert(ctx, conn, name, &smb_fname, 0);
1004 if (!NT_STATUS_IS_OK(status)) {
1008 status = get_full_smb_filename(ctx, smb_fname, &name);
1009 if (!NT_STATUS_IS_OK(status)) {
1013 status = check_name(conn, name);
1014 if (!NT_STATUS_IS_OK(status)) {
1015 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
1019 if (!VALID_STAT(smb_fname->st) &&
1020 (SMB_VFS_STAT(conn, name, &smb_fname->st) != 0)) {
1021 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
1022 status = map_nt_error_from_unix(errno);
1026 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1027 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1028 ERRDOS, ERRbadpath);
1032 reply_outbuf(req, 0, 0);
1034 TALLOC_FREE(smb_fname);
1035 END_PROFILE(SMBcheckpath);
1040 TALLOC_FREE(smb_fname);
1042 END_PROFILE(SMBcheckpath);
1044 /* We special case this - as when a Windows machine
1045 is parsing a path is steps through the components
1046 one at a time - if a component fails it expects
1047 ERRbadpath, not ERRbadfile.
1049 status = map_checkpath_error(req->flags2, status);
1050 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1052 * Windows returns different error codes if
1053 * the parent directory is valid but not the
1054 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1055 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1056 * if the path is invalid.
1058 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1059 ERRDOS, ERRbadpath);
1063 reply_nterror(req, status);
1066 /****************************************************************************
1068 ****************************************************************************/
1070 void reply_getatr(struct smb_request *req)
1072 connection_struct *conn = req->conn;
1073 struct smb_filename *smb_fname = NULL;
1080 TALLOC_CTX *ctx = talloc_tos();
1082 START_PROFILE(SMBgetatr);
1084 p = (const char *)req->buf + 1;
1085 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1086 if (!NT_STATUS_IS_OK(status)) {
1087 reply_nterror(req, status);
1091 status = resolve_dfspath(ctx, conn,
1092 req->flags2 & FLAGS2_DFS_PATHNAMES,
1095 if (!NT_STATUS_IS_OK(status)) {
1096 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1097 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1098 ERRSRV, ERRbadpath);
1101 reply_nterror(req, status);
1105 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1106 under WfWg - weird! */
1107 if (*fname == '\0') {
1108 mode = aHIDDEN | aDIR;
1109 if (!CAN_WRITE(conn)) {
1115 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1116 if (!NT_STATUS_IS_OK(status)) {
1117 reply_nterror(req, status);
1120 status = get_full_smb_filename(ctx, smb_fname, &fname);
1121 if (!NT_STATUS_IS_OK(status)) {
1122 reply_nterror(req, status);
1125 status = check_name(conn, fname);
1126 if (!NT_STATUS_IS_OK(status)) {
1127 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1128 reply_nterror(req, status);
1131 if (!VALID_STAT(smb_fname->st) &&
1132 (SMB_VFS_STAT(conn, fname, &smb_fname->st) != 0)) {
1133 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1134 reply_unixerror(req, ERRDOS,ERRbadfile);
1138 mode = dos_mode(conn, fname, &smb_fname->st);
1139 size = smb_fname->st.st_ex_size;
1140 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1146 reply_outbuf(req, 10, 0);
1148 SSVAL(req->outbuf,smb_vwv0,mode);
1149 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1150 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1152 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1154 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1156 if (Protocol >= PROTOCOL_NT1) {
1157 SSVAL(req->outbuf, smb_flg2,
1158 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1161 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1164 TALLOC_FREE(smb_fname);
1165 END_PROFILE(SMBgetatr);
1169 /****************************************************************************
1171 ****************************************************************************/
1173 void reply_setatr(struct smb_request *req)
1175 struct smb_file_time ft;
1176 connection_struct *conn = req->conn;
1177 struct smb_filename *smb_fname = NULL;
1183 TALLOC_CTX *ctx = talloc_tos();
1185 START_PROFILE(SMBsetatr);
1190 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1194 p = (const char *)req->buf + 1;
1195 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1196 if (!NT_STATUS_IS_OK(status)) {
1197 reply_nterror(req, status);
1201 status = resolve_dfspath(ctx, conn,
1202 req->flags2 & FLAGS2_DFS_PATHNAMES,
1205 if (!NT_STATUS_IS_OK(status)) {
1206 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1207 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1208 ERRSRV, ERRbadpath);
1211 reply_nterror(req, status);
1215 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1216 if (!NT_STATUS_IS_OK(status)) {
1217 reply_nterror(req, status);
1221 status = get_full_smb_filename(ctx, smb_fname, &fname);
1222 if (!NT_STATUS_IS_OK(status)) {
1223 reply_nterror(req, status);
1227 status = check_name(conn, fname);
1228 if (!NT_STATUS_IS_OK(status)) {
1229 reply_nterror(req, status);
1233 if (fname[0] == '.' && fname[1] == '\0') {
1235 * Not sure here is the right place to catch this
1236 * condition. Might be moved to somewhere else later -- vl
1238 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1242 mode = SVAL(req->vwv+0, 0);
1243 mtime = srv_make_unix_date3(req->vwv+1);
1245 ft.mtime = convert_time_t_to_timespec(mtime);
1246 status = smb_set_file_time(conn, NULL, fname,
1247 &smb_fname->st, &ft, true);
1248 if (!NT_STATUS_IS_OK(status)) {
1249 reply_unixerror(req, ERRDOS, ERRnoaccess);
1253 if (mode != FILE_ATTRIBUTE_NORMAL) {
1254 if (VALID_STAT_OF_DIR(smb_fname->st))
1259 if (file_set_dosmode(conn, fname, mode, &smb_fname->st, NULL,
1261 reply_unixerror(req, ERRDOS, ERRnoaccess);
1266 reply_outbuf(req, 0, 0);
1268 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1270 TALLOC_FREE(smb_fname);
1271 END_PROFILE(SMBsetatr);
1275 /****************************************************************************
1277 ****************************************************************************/
1279 void reply_dskattr(struct smb_request *req)
1281 connection_struct *conn = req->conn;
1282 uint64_t dfree,dsize,bsize;
1283 START_PROFILE(SMBdskattr);
1285 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1286 reply_unixerror(req, ERRHRD, ERRgeneral);
1287 END_PROFILE(SMBdskattr);
1291 reply_outbuf(req, 5, 0);
1293 if (Protocol <= PROTOCOL_LANMAN2) {
1294 double total_space, free_space;
1295 /* we need to scale this to a number that DOS6 can handle. We
1296 use floating point so we can handle large drives on systems
1297 that don't have 64 bit integers
1299 we end up displaying a maximum of 2G to DOS systems
1301 total_space = dsize * (double)bsize;
1302 free_space = dfree * (double)bsize;
1304 dsize = (uint64_t)((total_space+63*512) / (64*512));
1305 dfree = (uint64_t)((free_space+63*512) / (64*512));
1307 if (dsize > 0xFFFF) dsize = 0xFFFF;
1308 if (dfree > 0xFFFF) dfree = 0xFFFF;
1310 SSVAL(req->outbuf,smb_vwv0,dsize);
1311 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1312 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1313 SSVAL(req->outbuf,smb_vwv3,dfree);
1315 SSVAL(req->outbuf,smb_vwv0,dsize);
1316 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1317 SSVAL(req->outbuf,smb_vwv2,512);
1318 SSVAL(req->outbuf,smb_vwv3,dfree);
1321 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1323 END_PROFILE(SMBdskattr);
1327 /****************************************************************************
1329 Can be called from SMBsearch, SMBffirst or SMBfunique.
1330 ****************************************************************************/
1332 void reply_search(struct smb_request *req)
1334 connection_struct *conn = req->conn;
1335 const char *mask = NULL;
1336 char *directory = NULL;
1340 struct timespec date;
1342 unsigned int numentries = 0;
1343 unsigned int maxentries = 0;
1344 bool finished = False;
1350 bool check_descend = False;
1351 bool expect_close = False;
1353 bool mask_contains_wcard = False;
1354 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1355 TALLOC_CTX *ctx = talloc_tos();
1356 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1358 START_PROFILE(SMBsearch);
1361 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1362 END_PROFILE(SMBsearch);
1366 if (lp_posix_pathnames()) {
1367 reply_unknown_new(req, req->cmd);
1368 END_PROFILE(SMBsearch);
1372 /* If we were called as SMBffirst then we must expect close. */
1373 if(req->cmd == SMBffirst) {
1374 expect_close = True;
1377 reply_outbuf(req, 1, 3);
1378 maxentries = SVAL(req->vwv+0, 0);
1379 dirtype = SVAL(req->vwv+1, 0);
1380 p = (const char *)req->buf + 1;
1381 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1382 &nt_status, &mask_contains_wcard);
1383 if (!NT_STATUS_IS_OK(nt_status)) {
1384 reply_nterror(req, nt_status);
1385 END_PROFILE(SMBsearch);
1389 nt_status = resolve_dfspath_wcard(ctx, conn,
1390 req->flags2 & FLAGS2_DFS_PATHNAMES,
1393 &mask_contains_wcard);
1394 if (!NT_STATUS_IS_OK(nt_status)) {
1395 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1396 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1397 ERRSRV, ERRbadpath);
1398 END_PROFILE(SMBsearch);
1401 reply_nterror(req, nt_status);
1402 END_PROFILE(SMBsearch);
1407 status_len = SVAL(p, 0);
1410 /* dirtype &= ~aDIR; */
1412 if (status_len == 0) {
1413 struct smb_filename *smb_fname = NULL;
1415 nt_status = unix_convert(ctx, conn, path, &smb_fname,
1416 UCF_ALLOW_WCARD_LCOMP);
1417 if (!NT_STATUS_IS_OK(nt_status)) {
1418 reply_nterror(req, nt_status);
1419 END_PROFILE(SMBsearch);
1423 nt_status = get_full_smb_filename(ctx, smb_fname, &directory);
1424 TALLOC_FREE(smb_fname);
1425 if (!NT_STATUS_IS_OK(nt_status)) {
1426 reply_nterror(req, nt_status);
1427 END_PROFILE(SMBsearch);
1431 nt_status = check_name(conn, directory);
1432 if (!NT_STATUS_IS_OK(nt_status)) {
1433 reply_nterror(req, nt_status);
1434 END_PROFILE(SMBsearch);
1438 p = strrchr_m(directory,'/');
1439 if ((p != NULL) && (*directory != '/')) {
1441 directory = talloc_strndup(ctx, directory,
1442 PTR_DIFF(p, directory));
1445 directory = talloc_strdup(ctx,".");
1449 reply_nterror(req, NT_STATUS_NO_MEMORY);
1450 END_PROFILE(SMBsearch);
1454 memset((char *)status,'\0',21);
1455 SCVAL(status,0,(dirtype & 0x1F));
1457 nt_status = dptr_create(conn,
1463 mask_contains_wcard,
1466 if (!NT_STATUS_IS_OK(nt_status)) {
1467 reply_nterror(req, nt_status);
1468 END_PROFILE(SMBsearch);
1471 dptr_num = dptr_dnum(conn->dirptr);
1475 memcpy(status,p,21);
1476 status_dirtype = CVAL(status,0) & 0x1F;
1477 if (status_dirtype != (dirtype & 0x1F)) {
1478 dirtype = status_dirtype;
1481 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1482 if (!conn->dirptr) {
1485 string_set(&conn->dirpath,dptr_path(dptr_num));
1486 mask = dptr_wcard(dptr_num);
1491 * For a 'continue' search we have no string. So
1492 * check from the initial saved string.
1494 mask_contains_wcard = ms_has_wild(mask);
1495 dirtype = dptr_attr(dptr_num);
1498 DEBUG(4,("dptr_num is %d\n",dptr_num));
1500 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1501 dptr_init_search_op(conn->dirptr);
1503 if ((dirtype&0x1F) == aVOLID) {
1504 char buf[DIR_STRUCT_SIZE];
1505 memcpy(buf,status,21);
1506 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1507 0,aVOLID,0,!allow_long_path_components)) {
1508 reply_nterror(req, NT_STATUS_NO_MEMORY);
1509 END_PROFILE(SMBsearch);
1512 dptr_fill(buf+12,dptr_num);
1513 if (dptr_zero(buf+12) && (status_len==0)) {
1518 if (message_push_blob(&req->outbuf,
1519 data_blob_const(buf, sizeof(buf)))
1521 reply_nterror(req, NT_STATUS_NO_MEMORY);
1522 END_PROFILE(SMBsearch);
1530 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1533 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1534 conn->dirpath,lp_dontdescend(SNUM(conn))));
1535 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1536 check_descend = True;
1539 for (i=numentries;(i<maxentries) && !finished;i++) {
1540 finished = !get_dir_entry(ctx,
1551 char buf[DIR_STRUCT_SIZE];
1552 memcpy(buf,status,21);
1553 if (!make_dir_struct(ctx,
1559 convert_timespec_to_time_t(date),
1560 !allow_long_path_components)) {
1561 reply_nterror(req, NT_STATUS_NO_MEMORY);
1562 END_PROFILE(SMBsearch);
1565 if (!dptr_fill(buf+12,dptr_num)) {
1568 if (message_push_blob(&req->outbuf,
1569 data_blob_const(buf, sizeof(buf)))
1571 reply_nterror(req, NT_STATUS_NO_MEMORY);
1572 END_PROFILE(SMBsearch);
1582 /* If we were called as SMBffirst with smb_search_id == NULL
1583 and no entries were found then return error and close dirptr
1586 if (numentries == 0) {
1587 dptr_close(&dptr_num);
1588 } else if(expect_close && status_len == 0) {
1589 /* Close the dptr - we know it's gone */
1590 dptr_close(&dptr_num);
1593 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1594 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1595 dptr_close(&dptr_num);
1598 if ((numentries == 0) && !mask_contains_wcard) {
1599 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1600 END_PROFILE(SMBsearch);
1604 SSVAL(req->outbuf,smb_vwv0,numentries);
1605 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1606 SCVAL(smb_buf(req->outbuf),0,5);
1607 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1609 /* The replies here are never long name. */
1610 SSVAL(req->outbuf, smb_flg2,
1611 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1612 if (!allow_long_path_components) {
1613 SSVAL(req->outbuf, smb_flg2,
1614 SVAL(req->outbuf, smb_flg2)
1615 & (~FLAGS2_LONG_PATH_COMPONENTS));
1618 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1619 SSVAL(req->outbuf, smb_flg2,
1620 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1623 directory = dptr_path(dptr_num);
1626 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1627 smb_fn_name(req->cmd),
1629 directory ? directory : "./",
1634 END_PROFILE(SMBsearch);
1638 /****************************************************************************
1639 Reply to a fclose (stop directory search).
1640 ****************************************************************************/
1642 void reply_fclose(struct smb_request *req)
1650 bool path_contains_wcard = False;
1651 TALLOC_CTX *ctx = talloc_tos();
1653 START_PROFILE(SMBfclose);
1655 if (lp_posix_pathnames()) {
1656 reply_unknown_new(req, req->cmd);
1657 END_PROFILE(SMBfclose);
1661 p = (const char *)req->buf + 1;
1662 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1663 &err, &path_contains_wcard);
1664 if (!NT_STATUS_IS_OK(err)) {
1665 reply_nterror(req, err);
1666 END_PROFILE(SMBfclose);
1670 status_len = SVAL(p,0);
1673 if (status_len == 0) {
1674 reply_doserror(req, ERRSRV, ERRsrverror);
1675 END_PROFILE(SMBfclose);
1679 memcpy(status,p,21);
1681 if(dptr_fetch(status+12,&dptr_num)) {
1682 /* Close the dptr - we know it's gone */
1683 dptr_close(&dptr_num);
1686 reply_outbuf(req, 1, 0);
1687 SSVAL(req->outbuf,smb_vwv0,0);
1689 DEBUG(3,("search close\n"));
1691 END_PROFILE(SMBfclose);
1695 /****************************************************************************
1697 ****************************************************************************/
1699 void reply_open(struct smb_request *req)
1701 connection_struct *conn = req->conn;
1707 SMB_STRUCT_STAT sbuf;
1714 uint32 create_disposition;
1715 uint32 create_options = 0;
1717 TALLOC_CTX *ctx = talloc_tos();
1719 START_PROFILE(SMBopen);
1721 SET_STAT_INVALID(sbuf);
1724 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1725 END_PROFILE(SMBopen);
1729 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1730 deny_mode = SVAL(req->vwv+0, 0);
1731 dos_attr = SVAL(req->vwv+1, 0);
1733 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1734 STR_TERMINATE, &status);
1735 if (!NT_STATUS_IS_OK(status)) {
1736 reply_nterror(req, status);
1737 END_PROFILE(SMBopen);
1741 if (!map_open_params_to_ntcreate(
1742 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1743 &share_mode, &create_disposition, &create_options)) {
1744 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1745 END_PROFILE(SMBopen);
1749 status = SMB_VFS_CREATE_FILE(
1752 0, /* root_dir_fid */
1754 CFF_DOS_PATH, /* create_file_flags */
1755 access_mask, /* access_mask */
1756 share_mode, /* share_access */
1757 create_disposition, /* create_disposition*/
1758 create_options, /* create_options */
1759 dos_attr, /* file_attributes */
1760 oplock_request, /* oplock_request */
1761 0, /* allocation_size */
1768 if (!NT_STATUS_IS_OK(status)) {
1769 if (open_was_deferred(req->mid)) {
1770 /* We have re-scheduled this call. */
1771 END_PROFILE(SMBopen);
1774 reply_openerror(req, status);
1775 END_PROFILE(SMBopen);
1779 size = sbuf.st_ex_size;
1780 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1781 mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime);
1784 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1785 close_file(req, fsp, ERROR_CLOSE);
1786 reply_doserror(req, ERRDOS,ERRnoaccess);
1787 END_PROFILE(SMBopen);
1791 reply_outbuf(req, 7, 0);
1792 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1793 SSVAL(req->outbuf,smb_vwv1,fattr);
1794 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1795 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1797 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1799 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1800 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1802 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1803 SCVAL(req->outbuf,smb_flg,
1804 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1807 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1808 SCVAL(req->outbuf,smb_flg,
1809 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1811 END_PROFILE(SMBopen);
1815 /****************************************************************************
1816 Reply to an open and X.
1817 ****************************************************************************/
1819 void reply_open_and_X(struct smb_request *req)
1821 connection_struct *conn = req->conn;
1826 /* Breakout the oplock request bits so we can set the
1827 reply bits separately. */
1828 int ex_oplock_request;
1829 int core_oplock_request;
1832 int smb_sattr = SVAL(req->vwv+4, 0);
1833 uint32 smb_time = make_unix_date3(req->vwv+6);
1838 SMB_STRUCT_STAT sbuf;
1842 uint64_t allocation_size;
1843 ssize_t retval = -1;
1846 uint32 create_disposition;
1847 uint32 create_options = 0;
1848 TALLOC_CTX *ctx = talloc_tos();
1850 START_PROFILE(SMBopenX);
1852 if (req->wct < 15) {
1853 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1854 END_PROFILE(SMBopenX);
1858 SET_STAT_INVALID(sbuf);
1860 open_flags = SVAL(req->vwv+2, 0);
1861 deny_mode = SVAL(req->vwv+3, 0);
1862 smb_attr = SVAL(req->vwv+5, 0);
1863 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1864 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1865 oplock_request = ex_oplock_request | core_oplock_request;
1866 smb_ofun = SVAL(req->vwv+8, 0);
1867 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1869 /* If it's an IPC, pass off the pipe handler. */
1871 if (lp_nt_pipe_support()) {
1872 reply_open_pipe_and_X(conn, req);
1874 reply_doserror(req, ERRSRV, ERRaccess);
1876 END_PROFILE(SMBopenX);
1880 /* XXXX we need to handle passed times, sattr and flags */
1881 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1882 STR_TERMINATE, &status);
1883 if (!NT_STATUS_IS_OK(status)) {
1884 reply_nterror(req, status);
1885 END_PROFILE(SMBopenX);
1889 if (!map_open_params_to_ntcreate(
1890 fname, deny_mode, smb_ofun, &access_mask,
1891 &share_mode, &create_disposition, &create_options)) {
1892 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1893 END_PROFILE(SMBopenX);
1897 status = SMB_VFS_CREATE_FILE(
1900 0, /* root_dir_fid */
1902 CFF_DOS_PATH, /* create_file_flags */
1903 access_mask, /* access_mask */
1904 share_mode, /* share_access */
1905 create_disposition, /* create_disposition*/
1906 create_options, /* create_options */
1907 smb_attr, /* file_attributes */
1908 oplock_request, /* oplock_request */
1909 0, /* allocation_size */
1913 &smb_action, /* pinfo */
1916 if (!NT_STATUS_IS_OK(status)) {
1917 END_PROFILE(SMBopenX);
1918 if (open_was_deferred(req->mid)) {
1919 /* We have re-scheduled this call. */
1922 reply_openerror(req, status);
1926 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1927 if the file is truncated or created. */
1928 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1929 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1930 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1931 close_file(req, fsp, ERROR_CLOSE);
1932 reply_nterror(req, NT_STATUS_DISK_FULL);
1933 END_PROFILE(SMBopenX);
1936 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1938 close_file(req, fsp, ERROR_CLOSE);
1939 reply_nterror(req, NT_STATUS_DISK_FULL);
1940 END_PROFILE(SMBopenX);
1943 sbuf.st_ex_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
1946 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1947 mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime);
1949 close_file(req, fsp, ERROR_CLOSE);
1950 reply_doserror(req, ERRDOS, ERRnoaccess);
1951 END_PROFILE(SMBopenX);
1955 /* If the caller set the extended oplock request bit
1956 and we granted one (by whatever means) - set the
1957 correct bit for extended oplock reply.
1960 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1961 smb_action |= EXTENDED_OPLOCK_GRANTED;
1964 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1965 smb_action |= EXTENDED_OPLOCK_GRANTED;
1968 /* If the caller set the core oplock request bit
1969 and we granted one (by whatever means) - set the
1970 correct bit for core oplock reply.
1973 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1974 reply_outbuf(req, 19, 0);
1976 reply_outbuf(req, 15, 0);
1979 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1980 SCVAL(req->outbuf, smb_flg,
1981 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1984 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1985 SCVAL(req->outbuf, smb_flg,
1986 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1989 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1990 SSVAL(req->outbuf,smb_vwv3,fattr);
1991 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1992 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1994 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1996 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_ex_size);
1997 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1998 SSVAL(req->outbuf,smb_vwv11,smb_action);
2000 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2001 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2004 END_PROFILE(SMBopenX);
2009 /****************************************************************************
2010 Reply to a SMBulogoffX.
2011 ****************************************************************************/
2013 void reply_ulogoffX(struct smb_request *req)
2017 START_PROFILE(SMBulogoffX);
2019 vuser = get_valid_user_struct(req->vuid);
2022 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2026 /* in user level security we are supposed to close any files
2027 open by this user */
2028 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2029 file_close_user(req->vuid);
2032 invalidate_vuid(req->vuid);
2034 reply_outbuf(req, 2, 0);
2036 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2038 END_PROFILE(SMBulogoffX);
2042 /****************************************************************************
2043 Reply to a mknew or a create.
2044 ****************************************************************************/
2046 void reply_mknew(struct smb_request *req)
2048 connection_struct *conn = req->conn;
2051 struct smb_file_time ft;
2053 int oplock_request = 0;
2054 SMB_STRUCT_STAT sbuf;
2056 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2057 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2058 uint32 create_disposition;
2059 uint32 create_options = 0;
2060 TALLOC_CTX *ctx = talloc_tos();
2062 START_PROFILE(SMBcreate);
2064 SET_STAT_INVALID(sbuf);
2067 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2068 END_PROFILE(SMBcreate);
2072 fattr = SVAL(req->vwv+0, 0);
2073 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2076 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2078 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2079 STR_TERMINATE, &status);
2080 if (!NT_STATUS_IS_OK(status)) {
2081 reply_nterror(req, status);
2082 END_PROFILE(SMBcreate);
2086 if (fattr & aVOLID) {
2087 DEBUG(0,("Attempt to create file (%s) with volid set - "
2088 "please report this\n", fname));
2091 if(req->cmd == SMBmknew) {
2092 /* We should fail if file exists. */
2093 create_disposition = FILE_CREATE;
2095 /* Create if file doesn't exist, truncate if it does. */
2096 create_disposition = FILE_OVERWRITE_IF;
2099 status = SMB_VFS_CREATE_FILE(
2102 0, /* root_dir_fid */
2104 CFF_DOS_PATH, /* create_file_flags */
2105 access_mask, /* access_mask */
2106 share_mode, /* share_access */
2107 create_disposition, /* create_disposition*/
2108 create_options, /* create_options */
2109 fattr, /* file_attributes */
2110 oplock_request, /* oplock_request */
2111 0, /* allocation_size */
2118 if (!NT_STATUS_IS_OK(status)) {
2119 END_PROFILE(SMBcreate);
2120 if (open_was_deferred(req->mid)) {
2121 /* We have re-scheduled this call. */
2124 reply_openerror(req, status);
2128 ft.atime = sbuf.st_ex_atime; /* atime. */
2129 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true);
2130 if (!NT_STATUS_IS_OK(status)) {
2131 END_PROFILE(SMBcreate);
2132 reply_openerror(req, status);
2136 reply_outbuf(req, 1, 0);
2137 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2139 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2140 SCVAL(req->outbuf,smb_flg,
2141 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2144 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2145 SCVAL(req->outbuf,smb_flg,
2146 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2149 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2150 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2151 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2153 END_PROFILE(SMBcreate);
2157 /****************************************************************************
2158 Reply to a create temporary file.
2159 ****************************************************************************/
2161 void reply_ctemp(struct smb_request *req)
2163 connection_struct *conn = req->conn;
2164 struct smb_filename *smb_fname = NULL;
2172 TALLOC_CTX *ctx = talloc_tos();
2174 START_PROFILE(SMBctemp);
2177 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2181 fattr = SVAL(req->vwv+0, 0);
2182 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2184 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2185 STR_TERMINATE, &status);
2186 if (!NT_STATUS_IS_OK(status)) {
2187 reply_nterror(req, status);
2191 fname = talloc_asprintf(ctx,
2195 fname = talloc_strdup(ctx, "TMXXXXXX");
2199 reply_nterror(req, NT_STATUS_NO_MEMORY);
2203 status = resolve_dfspath(ctx, conn,
2204 req->flags2 & FLAGS2_DFS_PATHNAMES,
2207 if (!NT_STATUS_IS_OK(status)) {
2208 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2209 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2210 ERRSRV, ERRbadpath);
2213 reply_nterror(req, status);
2217 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
2218 if (!NT_STATUS_IS_OK(status)) {
2219 reply_nterror(req, status);
2223 status = get_full_smb_filename(ctx, smb_fname, &fname);
2224 if (!NT_STATUS_IS_OK(status)) {
2225 reply_nterror(req, status);
2229 status = check_name(conn, fname);
2230 if (!NT_STATUS_IS_OK(status)) {
2231 reply_nterror(req, status);
2235 tmpfd = mkstemp(fname);
2237 reply_unixerror(req, ERRDOS, ERRnoaccess);
2241 SET_STAT_INVALID(smb_fname->st);
2242 SMB_VFS_STAT(conn, fname, &smb_fname->st);
2244 /* We should fail if file does not exist. */
2245 status = SMB_VFS_CREATE_FILE(
2248 0, /* root_dir_fid */
2250 0, /* create_file_flags */
2251 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2252 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2253 FILE_OPEN, /* create_disposition*/
2254 0, /* create_options */
2255 fattr, /* file_attributes */
2256 oplock_request, /* oplock_request */
2257 0, /* allocation_size */
2262 &smb_fname->st); /* psbuf */
2264 /* close fd from mkstemp() */
2267 if (!NT_STATUS_IS_OK(status)) {
2268 if (open_was_deferred(req->mid)) {
2269 /* We have re-scheduled this call. */
2272 reply_openerror(req, status);
2276 reply_outbuf(req, 1, 0);
2277 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2279 /* the returned filename is relative to the directory */
2280 s = strrchr_m(fsp->fsp_name, '/');
2288 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2289 thing in the byte section. JRA */
2290 SSVALS(p, 0, -1); /* what is this? not in spec */
2292 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2294 reply_nterror(req, NT_STATUS_NO_MEMORY);
2298 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2299 SCVAL(req->outbuf, smb_flg,
2300 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2303 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2304 SCVAL(req->outbuf, smb_flg,
2305 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2308 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2309 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2310 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2312 TALLOC_FREE(smb_fname);
2313 END_PROFILE(SMBctemp);
2317 /*******************************************************************
2318 Check if a user is allowed to rename a file.
2319 ********************************************************************/
2321 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2322 uint16 dirtype, SMB_STRUCT_STAT *pst)
2326 if (!CAN_WRITE(conn)) {
2327 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2330 fmode = dos_mode(conn, fsp->fsp_name, pst);
2331 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2332 return NT_STATUS_NO_SUCH_FILE;
2335 if (S_ISDIR(pst->st_ex_mode)) {
2336 if (fsp->posix_open) {
2337 return NT_STATUS_OK;
2340 /* If no pathnames are open below this
2341 directory, allow the rename. */
2343 if (file_find_subpath(fsp)) {
2344 return NT_STATUS_ACCESS_DENIED;
2346 return NT_STATUS_OK;
2349 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2350 return NT_STATUS_OK;
2353 return NT_STATUS_ACCESS_DENIED;
2356 /*******************************************************************
2357 * unlink a file with all relevant access checks
2358 *******************************************************************/
2360 static NTSTATUS do_unlink(connection_struct *conn,
2361 struct smb_request *req,
2365 SMB_STRUCT_STAT sbuf;
2368 uint32 dirtype_orig = dirtype;
2371 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2373 if (!CAN_WRITE(conn)) {
2374 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2377 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2378 return map_nt_error_from_unix(errno);
2381 fattr = dos_mode(conn,fname,&sbuf);
2383 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2384 dirtype = aDIR|aARCH|aRONLY;
2387 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2389 return NT_STATUS_NO_SUCH_FILE;
2392 if (!dir_check_ftype(conn, fattr, dirtype)) {
2394 return NT_STATUS_FILE_IS_A_DIRECTORY;
2396 return NT_STATUS_NO_SUCH_FILE;
2399 if (dirtype_orig & 0x8000) {
2400 /* These will never be set for POSIX. */
2401 return NT_STATUS_NO_SUCH_FILE;
2405 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2406 return NT_STATUS_FILE_IS_A_DIRECTORY;
2409 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2410 return NT_STATUS_NO_SUCH_FILE;
2413 if (dirtype & 0xFF00) {
2414 /* These will never be set for POSIX. */
2415 return NT_STATUS_NO_SUCH_FILE;
2420 return NT_STATUS_NO_SUCH_FILE;
2423 /* Can't delete a directory. */
2425 return NT_STATUS_FILE_IS_A_DIRECTORY;
2430 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2431 return NT_STATUS_OBJECT_NAME_INVALID;
2432 #endif /* JRATEST */
2434 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2436 On a Windows share, a file with read-only dosmode can be opened with
2437 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2438 fails with NT_STATUS_CANNOT_DELETE error.
2440 This semantic causes a problem that a user can not
2441 rename a file with read-only dosmode on a Samba share
2442 from a Windows command prompt (i.e. cmd.exe, but can rename
2443 from Windows Explorer).
2446 if (!lp_delete_readonly(SNUM(conn))) {
2447 if (fattr & aRONLY) {
2448 return NT_STATUS_CANNOT_DELETE;
2452 /* On open checks the open itself will check the share mode, so
2453 don't do it here as we'll get it wrong. */
2455 status = SMB_VFS_CREATE_FILE
2458 0, /* root_dir_fid */
2460 0, /* create_file_flags */
2461 DELETE_ACCESS, /* access_mask */
2462 FILE_SHARE_NONE, /* share_access */
2463 FILE_OPEN, /* create_disposition*/
2464 FILE_NON_DIRECTORY_FILE, /* create_options */
2465 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2466 0, /* oplock_request */
2467 0, /* allocation_size */
2474 if (!NT_STATUS_IS_OK(status)) {
2475 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2476 nt_errstr(status)));
2480 /* The set is across all open files on this dev/inode pair. */
2481 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2482 close_file(req, fsp, NORMAL_CLOSE);
2483 return NT_STATUS_ACCESS_DENIED;
2486 return close_file(req, fsp, NORMAL_CLOSE);
2489 /****************************************************************************
2490 The guts of the unlink command, split out so it may be called by the NT SMB
2492 ****************************************************************************/
2494 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2495 uint32 dirtype, const char *name_in, bool has_wild)
2497 struct smb_filename *smb_fname = NULL;
2498 const char *directory = NULL;
2503 NTSTATUS status = NT_STATUS_OK;
2505 TALLOC_CTX *ctx = talloc_tos();
2507 status = unix_convert(ctx, conn, name_in, &smb_fname,
2508 has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
2509 if (!NT_STATUS_IS_OK(status)) {
2513 status = get_full_smb_filename(ctx, smb_fname, &name);
2514 if (!NT_STATUS_IS_OK(status)) {
2515 TALLOC_FREE(smb_fname);
2519 p = strrchr_m(name,'/');
2521 directory = talloc_strdup(ctx, ".");
2523 TALLOC_FREE(smb_fname);
2524 return NT_STATUS_NO_MEMORY;
2534 * We should only check the mangled cache
2535 * here if unix_convert failed. This means
2536 * that the path in 'mask' doesn't exist
2537 * on the file system and so we need to look
2538 * for a possible mangle. This patch from
2539 * Tine Smukavec <valentin.smukavec@hermes.si>.
2542 if (!VALID_STAT(smb_fname->st) && mangle_is_mangled(mask,conn->params)) {
2543 char *new_mask = NULL;
2544 mangle_lookup_name_from_8_3(ctx,
2552 TALLOC_FREE(smb_fname);
2555 directory = talloc_asprintf(ctx,
2560 return NT_STATUS_NO_MEMORY;
2563 dirtype = FILE_ATTRIBUTE_NORMAL;
2566 status = check_name(conn, directory);
2567 if (!NT_STATUS_IS_OK(status)) {
2571 status = do_unlink(conn, req, directory, dirtype);
2572 if (!NT_STATUS_IS_OK(status)) {
2578 struct smb_Dir *dir_hnd = NULL;
2582 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2583 return NT_STATUS_OBJECT_NAME_INVALID;
2586 if (strequal(mask,"????????.???")) {
2591 status = check_name(conn, directory);
2592 if (!NT_STATUS_IS_OK(status)) {
2596 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2598 if (dir_hnd == NULL) {
2599 return map_nt_error_from_unix(errno);
2602 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2603 the pattern matches against the long name, otherwise the short name
2604 We don't implement this yet XXXX
2607 status = NT_STATUS_NO_SUCH_FILE;
2609 while ((dname = ReadDirName(dir_hnd, &offset, &st))) {
2612 if (!is_visible_file(conn, directory, dname, &st,
2618 /* Quick check for "." and ".." */
2619 if (ISDOT(dname) || ISDOTDOT(dname)) {
2623 if(!mask_match(dname, mask, conn->case_sensitive)) {
2627 fname = talloc_asprintf(ctx, "%s/%s",
2631 return NT_STATUS_NO_MEMORY;
2634 status = check_name(conn, fname);
2635 if (!NT_STATUS_IS_OK(status)) {
2636 TALLOC_FREE(dir_hnd);
2640 status = do_unlink(conn, req, fname, dirtype);
2641 if (!NT_STATUS_IS_OK(status)) {
2647 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2652 TALLOC_FREE(dir_hnd);
2655 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2656 status = map_nt_error_from_unix(errno);
2662 /****************************************************************************
2664 ****************************************************************************/
2666 void reply_unlink(struct smb_request *req)
2668 connection_struct *conn = req->conn;
2672 bool path_contains_wcard = False;
2673 TALLOC_CTX *ctx = talloc_tos();
2675 START_PROFILE(SMBunlink);
2678 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2679 END_PROFILE(SMBunlink);
2683 dirtype = SVAL(req->vwv+0, 0);
2685 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2686 STR_TERMINATE, &status,
2687 &path_contains_wcard);
2688 if (!NT_STATUS_IS_OK(status)) {
2689 reply_nterror(req, status);
2690 END_PROFILE(SMBunlink);
2694 status = resolve_dfspath_wcard(ctx, conn,
2695 req->flags2 & FLAGS2_DFS_PATHNAMES,
2698 &path_contains_wcard);
2699 if (!NT_STATUS_IS_OK(status)) {
2700 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2701 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2702 ERRSRV, ERRbadpath);
2703 END_PROFILE(SMBunlink);
2706 reply_nterror(req, status);
2707 END_PROFILE(SMBunlink);
2711 DEBUG(3,("reply_unlink : %s\n",name));
2713 status = unlink_internals(conn, req, dirtype, name,
2714 path_contains_wcard);
2715 if (!NT_STATUS_IS_OK(status)) {
2716 if (open_was_deferred(req->mid)) {
2717 /* We have re-scheduled this call. */
2718 END_PROFILE(SMBunlink);
2721 reply_nterror(req, status);
2722 END_PROFILE(SMBunlink);
2726 reply_outbuf(req, 0, 0);
2727 END_PROFILE(SMBunlink);
2732 /****************************************************************************
2734 ****************************************************************************/
2736 static void fail_readraw(void)
2738 const char *errstr = talloc_asprintf(talloc_tos(),
2739 "FAIL ! reply_readbraw: socket write fail (%s)",
2744 exit_server_cleanly(errstr);
2747 /****************************************************************************
2748 Fake (read/write) sendfile. Returns -1 on read or write fail.
2749 ****************************************************************************/
2751 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2755 size_t tosend = nread;
2762 bufsize = MIN(nread, 65536);
2764 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2768 while (tosend > 0) {
2772 if (tosend > bufsize) {
2777 ret = read_file(fsp,buf,startpos,cur_read);
2783 /* If we had a short read, fill with zeros. */
2784 if (ret < cur_read) {
2785 memset(buf + ret, '\0', cur_read - ret);
2788 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2793 startpos += cur_read;
2797 return (ssize_t)nread;
2800 #if defined(WITH_SENDFILE)
2801 /****************************************************************************
2802 Deal with the case of sendfile reading less bytes from the file than
2803 requested. Fill with zeros (all we can do).
2804 ****************************************************************************/
2806 static void sendfile_short_send(files_struct *fsp,
2811 #define SHORT_SEND_BUFSIZE 1024
2812 if (nread < headersize) {
2813 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2814 "header for file %s (%s). Terminating\n",
2815 fsp->fsp_name, strerror(errno) ));
2816 exit_server_cleanly("sendfile_short_send failed");
2819 nread -= headersize;
2821 if (nread < smb_maxcnt) {
2822 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2824 exit_server_cleanly("sendfile_short_send: "
2828 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2829 "with zeros !\n", fsp->fsp_name));
2831 while (nread < smb_maxcnt) {
2833 * We asked for the real file size and told sendfile
2834 * to not go beyond the end of the file. But it can
2835 * happen that in between our fstat call and the
2836 * sendfile call the file was truncated. This is very
2837 * bad because we have already announced the larger
2838 * number of bytes to the client.
2840 * The best we can do now is to send 0-bytes, just as
2841 * a read from a hole in a sparse file would do.
2843 * This should happen rarely enough that I don't care
2844 * about efficiency here :-)
2848 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2849 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2850 exit_server_cleanly("sendfile_short_send: "
2851 "write_data failed");
2858 #endif /* defined WITH_SENDFILE */
2860 /****************************************************************************
2861 Return a readbraw error (4 bytes of zero).
2862 ****************************************************************************/
2864 static void reply_readbraw_error(void)
2868 if (write_data(smbd_server_fd(),header,4) != 4) {
2873 /****************************************************************************
2874 Use sendfile in readbraw.
2875 ****************************************************************************/
2877 static void send_file_readbraw(connection_struct *conn,
2878 struct smb_request *req,
2884 char *outbuf = NULL;
2887 #if defined(WITH_SENDFILE)
2889 * We can only use sendfile on a non-chained packet
2890 * but we can use on a non-oplocked file. tridge proved this
2891 * on a train in Germany :-). JRA.
2892 * reply_readbraw has already checked the length.
2895 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2896 (fsp->wcp == NULL) &&
2897 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2898 ssize_t sendfile_read = -1;
2900 DATA_BLOB header_blob;
2902 _smb_setlen(header,nread);
2903 header_blob = data_blob_const(header, 4);
2905 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2906 &header_blob, startpos, nread)) == -1) {
2907 /* Returning ENOSYS means no data at all was sent.
2908 * Do this as a normal read. */
2909 if (errno == ENOSYS) {
2910 goto normal_readbraw;
2914 * Special hack for broken Linux with no working sendfile. If we
2915 * return EINTR we sent the header but not the rest of the data.
2916 * Fake this up by doing read/write calls.
2918 if (errno == EINTR) {
2919 /* Ensure we don't do this again. */
2920 set_use_sendfile(SNUM(conn), False);
2921 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2923 if (fake_sendfile(fsp, startpos, nread) == -1) {
2924 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2925 fsp->fsp_name, strerror(errno) ));
2926 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2931 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2932 fsp->fsp_name, strerror(errno) ));
2933 exit_server_cleanly("send_file_readbraw sendfile failed");
2934 } else if (sendfile_read == 0) {
2936 * Some sendfile implementations return 0 to indicate
2937 * that there was a short read, but nothing was
2938 * actually written to the socket. In this case,
2939 * fallback to the normal read path so the header gets
2940 * the correct byte count.
2942 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2943 "bytes falling back to the normal read: "
2944 "%s\n", fsp->fsp_name));
2945 goto normal_readbraw;
2948 /* Deal with possible short send. */
2949 if (sendfile_read != 4+nread) {
2950 sendfile_short_send(fsp, sendfile_read, 4, nread);
2958 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2960 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2961 (unsigned)(nread+4)));
2962 reply_readbraw_error();
2967 ret = read_file(fsp,outbuf+4,startpos,nread);
2968 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2977 _smb_setlen(outbuf,ret);
2978 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2981 TALLOC_FREE(outbuf);
2984 /****************************************************************************
2985 Reply to a readbraw (core+ protocol).
2986 ****************************************************************************/
2988 void reply_readbraw(struct smb_request *req)
2990 connection_struct *conn = req->conn;
2991 ssize_t maxcount,mincount;
2995 struct lock_struct lock;
2999 START_PROFILE(SMBreadbraw);
3001 if (srv_is_signing_active(smbd_server_conn) ||
3002 is_encrypted_packet(req->inbuf)) {
3003 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3004 "raw reads/writes are disallowed.");
3008 reply_readbraw_error();
3009 END_PROFILE(SMBreadbraw);
3014 * Special check if an oplock break has been issued
3015 * and the readraw request croses on the wire, we must
3016 * return a zero length response here.
3019 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3022 * We have to do a check_fsp by hand here, as
3023 * we must always return 4 zero bytes on error,
3027 if (!fsp || !conn || conn != fsp->conn ||
3028 req->vuid != fsp->vuid ||
3029 fsp->is_directory || fsp->fh->fd == -1) {
3031 * fsp could be NULL here so use the value from the packet. JRA.
3033 DEBUG(3,("reply_readbraw: fnum %d not valid "
3035 (int)SVAL(req->vwv+0, 0)));
3036 reply_readbraw_error();
3037 END_PROFILE(SMBreadbraw);
3041 /* Do a "by hand" version of CHECK_READ. */
3042 if (!(fsp->can_read ||
3043 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3044 (fsp->access_mask & FILE_EXECUTE)))) {
3045 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3046 (int)SVAL(req->vwv+0, 0)));
3047 reply_readbraw_error();
3048 END_PROFILE(SMBreadbraw);
3052 flush_write_cache(fsp, READRAW_FLUSH);
3054 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3055 if(req->wct == 10) {
3057 * This is a large offset (64 bit) read.
3059 #ifdef LARGE_SMB_OFF_T
3061 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3063 #else /* !LARGE_SMB_OFF_T */
3066 * Ensure we haven't been sent a >32 bit offset.
3069 if(IVAL(req->vwv+8, 0) != 0) {
3070 DEBUG(0,("reply_readbraw: large offset "
3071 "(%x << 32) used and we don't support "
3072 "64 bit offsets.\n",
3073 (unsigned int)IVAL(req->vwv+8, 0) ));
3074 reply_readbraw_error();
3075 END_PROFILE(SMBreadbraw);
3079 #endif /* LARGE_SMB_OFF_T */
3082 DEBUG(0,("reply_readbraw: negative 64 bit "
3083 "readraw offset (%.0f) !\n",
3084 (double)startpos ));
3085 reply_readbraw_error();
3086 END_PROFILE(SMBreadbraw);
3091 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3092 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3094 /* ensure we don't overrun the packet size */
3095 maxcount = MIN(65535,maxcount);
3097 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3098 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3101 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3102 reply_readbraw_error();
3103 END_PROFILE(SMBreadbraw);
3107 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3108 size = st.st_ex_size;
3111 if (startpos >= size) {
3114 nread = MIN(maxcount,(size - startpos));
3117 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3118 if (nread < mincount)
3122 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3123 "min=%lu nread=%lu\n",
3124 fsp->fnum, (double)startpos,
3125 (unsigned long)maxcount,
3126 (unsigned long)mincount,
3127 (unsigned long)nread ) );
3129 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3131 DEBUG(5,("reply_readbraw finished\n"));
3133 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3135 END_PROFILE(SMBreadbraw);
3140 #define DBGC_CLASS DBGC_LOCKING
3142 /****************************************************************************
3143 Reply to a lockread (core+ protocol).
3144 ****************************************************************************/
3146 void reply_lockread(struct smb_request *req)
3148 connection_struct *conn = req->conn;
3155 struct byte_range_lock *br_lck = NULL;
3158 START_PROFILE(SMBlockread);
3161 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3162 END_PROFILE(SMBlockread);
3166 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3168 if (!check_fsp(conn, req, fsp)) {
3169 END_PROFILE(SMBlockread);
3173 if (!CHECK_READ(fsp,req)) {
3174 reply_doserror(req, ERRDOS, ERRbadaccess);
3175 END_PROFILE(SMBlockread);
3179 numtoread = SVAL(req->vwv+1, 0);
3180 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3182 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3184 reply_outbuf(req, 5, numtoread + 3);
3186 data = smb_buf(req->outbuf) + 3;
3189 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3190 * protocol request that predates the read/write lock concept.
3191 * Thus instead of asking for a read lock here we need to ask
3192 * for a write lock. JRA.
3193 * Note that the requested lock size is unaffected by max_recv.
3196 br_lck = do_lock(smbd_messaging_context(),
3199 (uint64_t)numtoread,
3203 False, /* Non-blocking lock. */
3207 TALLOC_FREE(br_lck);
3209 if (NT_STATUS_V(status)) {
3210 reply_nterror(req, status);
3211 END_PROFILE(SMBlockread);
3216 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3219 if (numtoread > max_recv) {
3220 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3221 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3222 (unsigned int)numtoread, (unsigned int)max_recv ));
3223 numtoread = MIN(numtoread,max_recv);
3225 nread = read_file(fsp,data,startpos,numtoread);
3228 reply_unixerror(req, ERRDOS, ERRnoaccess);
3229 END_PROFILE(SMBlockread);
3233 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3235 SSVAL(req->outbuf,smb_vwv0,nread);
3236 SSVAL(req->outbuf,smb_vwv5,nread+3);
3237 p = smb_buf(req->outbuf);
3238 SCVAL(p,0,0); /* pad byte. */
3241 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3242 fsp->fnum, (int)numtoread, (int)nread));
3244 END_PROFILE(SMBlockread);
3249 #define DBGC_CLASS DBGC_ALL
3251 /****************************************************************************
3253 ****************************************************************************/
3255 void reply_read(struct smb_request *req)
3257 connection_struct *conn = req->conn;
3264 struct lock_struct lock;
3266 START_PROFILE(SMBread);
3269 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3270 END_PROFILE(SMBread);
3274 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3276 if (!check_fsp(conn, req, fsp)) {
3277 END_PROFILE(SMBread);
3281 if (!CHECK_READ(fsp,req)) {
3282 reply_doserror(req, ERRDOS, ERRbadaccess);
3283 END_PROFILE(SMBread);
3287 numtoread = SVAL(req->vwv+1, 0);
3288 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3290 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3293 * The requested read size cannot be greater than max_recv. JRA.
3295 if (numtoread > max_recv) {
3296 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3297 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3298 (unsigned int)numtoread, (unsigned int)max_recv ));
3299 numtoread = MIN(numtoread,max_recv);
3302 reply_outbuf(req, 5, numtoread+3);
3304 data = smb_buf(req->outbuf) + 3;
3306 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3307 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3310 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3311 reply_doserror(req, ERRDOS,ERRlock);
3312 END_PROFILE(SMBread);
3317 nread = read_file(fsp,data,startpos,numtoread);
3320 reply_unixerror(req, ERRDOS,ERRnoaccess);
3324 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3326 SSVAL(req->outbuf,smb_vwv0,nread);
3327 SSVAL(req->outbuf,smb_vwv5,nread+3);
3328 SCVAL(smb_buf(req->outbuf),0,1);
3329 SSVAL(smb_buf(req->outbuf),1,nread);
3331 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3332 fsp->fnum, (int)numtoread, (int)nread ) );
3335 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3337 END_PROFILE(SMBread);
3341 /****************************************************************************
3343 ****************************************************************************/
3345 static int setup_readX_header(struct smb_request *req, char *outbuf,
3351 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3352 data = smb_buf(outbuf);
3354 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3356 SCVAL(outbuf,smb_vwv0,0xFF);
3357 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3358 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3359 SSVAL(outbuf,smb_vwv6,
3361 + 1 /* the wct field */
3362 + 12 * sizeof(uint16_t) /* vwv */
3363 + 2); /* the buflen field */
3364 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3365 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3366 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3367 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3371 /****************************************************************************
3372 Reply to a read and X - possibly using sendfile.
3373 ****************************************************************************/
3375 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3376 files_struct *fsp, SMB_OFF_T startpos,
3379 SMB_STRUCT_STAT sbuf;
3381 struct lock_struct lock;
3383 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3384 reply_unixerror(req, ERRDOS, ERRnoaccess);
3388 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3389 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3392 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3393 reply_doserror(req, ERRDOS, ERRlock);
3397 if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
3398 || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
3400 * We already know that we would do a short read, so don't
3401 * try the sendfile() path.
3403 goto nosendfile_read;
3406 #if defined(WITH_SENDFILE)
3408 * We can only use sendfile on a non-chained packet
3409 * but we can use on a non-oplocked file. tridge proved this
3410 * on a train in Germany :-). JRA.
3413 if (!req_is_in_chain(req) &&
3414 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3415 (fsp->wcp == NULL) &&
3416 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3417 uint8 headerbuf[smb_size + 12 * 2];
3421 * Set up the packet header before send. We
3422 * assume here the sendfile will work (get the
3423 * correct amount of data).
3426 header = data_blob_const(headerbuf, sizeof(headerbuf));
3428 construct_reply_common_req(req, (char *)headerbuf);
3429 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3431 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3432 /* Returning ENOSYS means no data at all was sent.
3433 Do this as a normal read. */
3434 if (errno == ENOSYS) {
3439 * Special hack for broken Linux with no working sendfile. If we
3440 * return EINTR we sent the header but not the rest of the data.
3441 * Fake this up by doing read/write calls.
3444 if (errno == EINTR) {
3445 /* Ensure we don't do this again. */
3446 set_use_sendfile(SNUM(conn), False);
3447 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3448 nread = fake_sendfile(fsp, startpos,
3451 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3452 fsp->fsp_name, strerror(errno) ));
3453 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3455 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3456 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3457 /* No outbuf here means successful sendfile. */
3461 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3462 fsp->fsp_name, strerror(errno) ));
3463 exit_server_cleanly("send_file_readX sendfile failed");
3464 } else if (nread == 0) {
3466 * Some sendfile implementations return 0 to indicate
3467 * that there was a short read, but nothing was
3468 * actually written to the socket. In this case,
3469 * fallback to the normal read path so the header gets
3470 * the correct byte count.
3472 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3473 "falling back to the normal read: %s\n",
3478 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3479 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3481 /* Deal with possible short send. */
3482 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3483 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3485 /* No outbuf here means successful sendfile. */
3486 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3487 SMB_PERFCOUNT_END(&req->pcd);
3495 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3496 uint8 headerbuf[smb_size + 2*12];
3498 construct_reply_common_req(req, (char *)headerbuf);
3499 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3501 /* Send out the header. */
3502 if (write_data(smbd_server_fd(), (char *)headerbuf,
3503 sizeof(headerbuf)) != sizeof(headerbuf)) {
3504 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3505 fsp->fsp_name, strerror(errno) ));
3506 exit_server_cleanly("send_file_readX sendfile failed");
3508 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3510 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3511 fsp->fsp_name, strerror(errno) ));
3512 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3519 reply_outbuf(req, 12, smb_maxcnt);
3521 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3523 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3526 reply_unixerror(req, ERRDOS, ERRnoaccess);
3530 setup_readX_header(req, (char *)req->outbuf, nread);
3532 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3533 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3539 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3540 TALLOC_FREE(req->outbuf);
3544 /****************************************************************************
3545 Reply to a read and X.
3546 ****************************************************************************/
3548 void reply_read_and_X(struct smb_request *req)
3550 connection_struct *conn = req->conn;
3554 bool big_readX = False;
3556 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3559 START_PROFILE(SMBreadX);
3561 if ((req->wct != 10) && (req->wct != 12)) {
3562 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3566 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3567 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3568 smb_maxcnt = SVAL(req->vwv+5, 0);
3570 /* If it's an IPC, pass off the pipe handler. */
3572 reply_pipe_read_and_X(req);
3573 END_PROFILE(SMBreadX);
3577 if (!check_fsp(conn, req, fsp)) {
3578 END_PROFILE(SMBreadX);
3582 if (!CHECK_READ(fsp,req)) {
3583 reply_doserror(req, ERRDOS,ERRbadaccess);
3584 END_PROFILE(SMBreadX);
3588 if (global_client_caps & CAP_LARGE_READX) {
3589 size_t upper_size = SVAL(req->vwv+7, 0);
3590 smb_maxcnt |= (upper_size<<16);
3591 if (upper_size > 1) {
3592 /* Can't do this on a chained packet. */
3593 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3594 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3595 END_PROFILE(SMBreadX);
3598 /* We currently don't do this on signed or sealed data. */
3599 if (srv_is_signing_active(smbd_server_conn) ||
3600 is_encrypted_packet(req->inbuf)) {
3601 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3602 END_PROFILE(SMBreadX);
3605 /* Is there room in the reply for this data ? */
3606 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3608 NT_STATUS_INVALID_PARAMETER);
3609 END_PROFILE(SMBreadX);
3616 if (req->wct == 12) {
3617 #ifdef LARGE_SMB_OFF_T
3619 * This is a large offset (64 bit) read.
3621 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3623 #else /* !LARGE_SMB_OFF_T */
3626 * Ensure we haven't been sent a >32 bit offset.
3629 if(IVAL(req->vwv+10, 0) != 0) {
3630 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3631 "used and we don't support 64 bit offsets.\n",
3632 (unsigned int)IVAL(req->vwv+10, 0) ));
3633 END_PROFILE(SMBreadX);
3634 reply_doserror(req, ERRDOS, ERRbadaccess);
3638 #endif /* LARGE_SMB_OFF_T */
3643 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3647 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3650 END_PROFILE(SMBreadX);
3654 /****************************************************************************
3655 Error replies to writebraw must have smb_wct == 1. Fix this up.
3656 ****************************************************************************/
3658 void error_to_writebrawerr(struct smb_request *req)
3660 uint8 *old_outbuf = req->outbuf;
3662 reply_outbuf(req, 1, 0);
3664 memcpy(req->outbuf, old_outbuf, smb_size);
3665 TALLOC_FREE(old_outbuf);
3668 /****************************************************************************
3669 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3670 ****************************************************************************/
3672 void reply_writebraw(struct smb_request *req)
3674 connection_struct *conn = req->conn;
3677 ssize_t total_written=0;
3678 size_t numtowrite=0;
3684 struct lock_struct lock;
3687 START_PROFILE(SMBwritebraw);
3690 * If we ever reply with an error, it must have the SMB command
3691 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3694 SCVAL(req->inbuf,smb_com,SMBwritec);
3696 if (srv_is_signing_active(smbd_server_conn)) {
3697 END_PROFILE(SMBwritebraw);
3698 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3699 "raw reads/writes are disallowed.");
3702 if (req->wct < 12) {
3703 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3704 error_to_writebrawerr(req);
3705 END_PROFILE(SMBwritebraw);
3709 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3710 if (!check_fsp(conn, req, fsp)) {
3711 error_to_writebrawerr(req);
3712 END_PROFILE(SMBwritebraw);
3716 if (!CHECK_WRITE(fsp)) {
3717 reply_doserror(req, ERRDOS, ERRbadaccess);
3718 error_to_writebrawerr(req);
3719 END_PROFILE(SMBwritebraw);
3723 tcount = IVAL(req->vwv+1, 0);
3724 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3725 write_through = BITSETW(req->vwv+7,0);
3727 /* We have to deal with slightly different formats depending
3728 on whether we are using the core+ or lanman1.0 protocol */
3730 if(Protocol <= PROTOCOL_COREPLUS) {
3731 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3732 data = smb_buf(req->inbuf);
3734 numtowrite = SVAL(req->vwv+10, 0);
3735 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3738 /* Ensure we don't write bytes past the end of this packet. */
3739 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3740 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3741 error_to_writebrawerr(req);
3742 END_PROFILE(SMBwritebraw);
3746 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3747 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3750 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3751 reply_doserror(req, ERRDOS, ERRlock);
3752 error_to_writebrawerr(req);
3753 END_PROFILE(SMBwritebraw);
3758 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3761 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3762 "wrote=%d sync=%d\n",
3763 fsp->fnum, (double)startpos, (int)numtowrite,
3764 (int)nwritten, (int)write_through));
3766 if (nwritten < (ssize_t)numtowrite) {
3767 reply_unixerror(req, ERRHRD, ERRdiskfull);
3768 error_to_writebrawerr(req);
3772 total_written = nwritten;
3774 /* Allocate a buffer of 64k + length. */
3775 buf = TALLOC_ARRAY(NULL, char, 65540);
3777 reply_doserror(req, ERRDOS, ERRnomem);
3778 error_to_writebrawerr(req);
3782 /* Return a SMBwritebraw message to the redirector to tell
3783 * it to send more bytes */
3785 memcpy(buf, req->inbuf, smb_size);
3786 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3787 SCVAL(buf,smb_com,SMBwritebraw);
3788 SSVALS(buf,smb_vwv0,0xFFFF);
3790 if (!srv_send_smb(smbd_server_fd(),
3792 false, 0, /* no signing */
3793 IS_CONN_ENCRYPTED(conn),
3795 exit_server_cleanly("reply_writebraw: srv_send_smb "
3799 /* Now read the raw data into the buffer and write it */
3800 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3802 if (!NT_STATUS_IS_OK(status)) {
3803 exit_server_cleanly("secondary writebraw failed");
3806 /* Set up outbuf to return the correct size */
3807 reply_outbuf(req, 1, 0);
3809 if (numtowrite != 0) {
3811 if (numtowrite > 0xFFFF) {
3812 DEBUG(0,("reply_writebraw: Oversize secondary write "
3813 "raw requested (%u). Terminating\n",
3814 (unsigned int)numtowrite ));
3815 exit_server_cleanly("secondary writebraw failed");
3818 if (tcount > nwritten+numtowrite) {
3819 DEBUG(3,("reply_writebraw: Client overestimated the "
3821 (int)tcount,(int)nwritten,(int)numtowrite));
3824 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3826 if (!NT_STATUS_IS_OK(status)) {
3827 DEBUG(0,("reply_writebraw: Oversize secondary write "
3828 "raw read failed (%s). Terminating\n",
3829 nt_errstr(status)));
3830 exit_server_cleanly("secondary writebraw failed");
3833 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3834 if (nwritten == -1) {
3836 reply_unixerror(req, ERRHRD, ERRdiskfull);
3837 error_to_writebrawerr(req);
3841 if (nwritten < (ssize_t)numtowrite) {
3842 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3843 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3847 total_written += nwritten;
3852 SSVAL(req->outbuf,smb_vwv0,total_written);
3854 status = sync_file(conn, fsp, write_through);
3855 if (!NT_STATUS_IS_OK(status)) {
3856 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3857 fsp->fsp_name, nt_errstr(status) ));
3858 reply_nterror(req, status);
3859 error_to_writebrawerr(req);
3863 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3865 fsp->fnum, (double)startpos, (int)numtowrite,
3866 (int)total_written));
3868 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3870 /* We won't return a status if write through is not selected - this
3871 * follows what WfWg does */
3872 END_PROFILE(SMBwritebraw);
3874 if (!write_through && total_written==tcount) {
3876 #if RABBIT_PELLET_FIX
3878 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3879 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3882 if (!send_keepalive(smbd_server_fd())) {
3883 exit_server_cleanly("reply_writebraw: send of "
3884 "keepalive failed");
3887 TALLOC_FREE(req->outbuf);
3892 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3894 END_PROFILE(SMBwritebraw);
3899 #define DBGC_CLASS DBGC_LOCKING
3901 /****************************************************************************
3902 Reply to a writeunlock (core+).
3903 ****************************************************************************/
3905 void reply_writeunlock(struct smb_request *req)
3907 connection_struct *conn = req->conn;
3908 ssize_t nwritten = -1;
3912 NTSTATUS status = NT_STATUS_OK;
3914 struct lock_struct lock;
3916 START_PROFILE(SMBwriteunlock);
3919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3920 END_PROFILE(SMBwriteunlock);
3924 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3926 if (!check_fsp(conn, req, fsp)) {
3927 END_PROFILE(SMBwriteunlock);
3931 if (!CHECK_WRITE(fsp)) {
3932 reply_doserror(req, ERRDOS,ERRbadaccess);
3933 END_PROFILE(SMBwriteunlock);
3937 numtowrite = SVAL(req->vwv+1, 0);
3938 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3939 data = (const char *)req->buf + 3;
3942 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3943 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3946 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3947 reply_doserror(req, ERRDOS, ERRlock);
3948 END_PROFILE(SMBwriteunlock);
3953 /* The special X/Open SMB protocol handling of
3954 zero length writes is *NOT* done for
3956 if(numtowrite == 0) {
3959 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3962 status = sync_file(conn, fsp, False /* write through */);
3963 if (!NT_STATUS_IS_OK(status)) {
3964 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3965 fsp->fsp_name, nt_errstr(status) ));
3966 reply_nterror(req, status);
3970 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3971 reply_unixerror(req, ERRHRD, ERRdiskfull);
3976 status = do_unlock(smbd_messaging_context(),
3979 (uint64_t)numtowrite,
3983 if (NT_STATUS_V(status)) {
3984 reply_nterror(req, status);
3989 reply_outbuf(req, 1, 0);
3991 SSVAL(req->outbuf,smb_vwv0,nwritten);
3993 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3994 fsp->fnum, (int)numtowrite, (int)nwritten));
3998 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4001 END_PROFILE(SMBwriteunlock);
4006 #define DBGC_CLASS DBGC_ALL
4008 /****************************************************************************
4010 ****************************************************************************/
4012 void reply_write(struct smb_request *req)
4014 connection_struct *conn = req->conn;
4016 ssize_t nwritten = -1;
4020 struct lock_struct lock;
4023 START_PROFILE(SMBwrite);
4026 END_PROFILE(SMBwrite);
4027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4031 /* If it's an IPC, pass off the pipe handler. */
4033 reply_pipe_write(req);
4034 END_PROFILE(SMBwrite);
4038 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4040 if (!check_fsp(conn, req, fsp)) {
4041 END_PROFILE(SMBwrite);
4045 if (!CHECK_WRITE(fsp)) {
4046 reply_doserror(req, ERRDOS, ERRbadaccess);
4047 END_PROFILE(SMBwrite);
4051 numtowrite = SVAL(req->vwv+1, 0);
4052 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4053 data = (const char *)req->buf + 3;
4055 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4056 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4059 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4060 reply_doserror(req, ERRDOS, ERRlock);
4061 END_PROFILE(SMBwrite);
4066 * X/Open SMB protocol says that if smb_vwv1 is
4067 * zero then the file size should be extended or
4068 * truncated to the size given in smb_vwv[2-3].
4071 if(numtowrite == 0) {
4073 * This is actually an allocate call, and set EOF. JRA.
4075 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4077 reply_nterror(req, NT_STATUS_DISK_FULL);
4080 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4082 reply_nterror(req, NT_STATUS_DISK_FULL);
4085 trigger_write_time_update_immediate(fsp);
4087 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4090 status = sync_file(conn, fsp, False);
4091 if (!NT_STATUS_IS_OK(status)) {
4092 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4093 fsp->fsp_name, nt_errstr(status) ));
4094 reply_nterror(req, status);
4098 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4099 reply_unixerror(req, ERRHRD, ERRdiskfull);
4103 reply_outbuf(req, 1, 0);
4105 SSVAL(req->outbuf,smb_vwv0,nwritten);
4107 if (nwritten < (ssize_t)numtowrite) {
4108 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4109 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4112 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4115 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4117 END_PROFILE(SMBwrite);
4121 /****************************************************************************
4122 Ensure a buffer is a valid writeX for recvfile purposes.
4123 ****************************************************************************/
4125 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4126 (2*14) + /* word count (including bcc) */ \
4129 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4132 connection_struct *conn = NULL;
4133 unsigned int doff = 0;
4134 size_t len = smb_len_large(inbuf);
4136 if (is_encrypted_packet(inbuf)) {
4137 /* Can't do this on encrypted
4142 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4146 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4147 CVAL(inbuf,smb_wct) != 14) {
4148 DEBUG(10,("is_valid_writeX_buffer: chained or "
4149 "invalid word length.\n"));
4153 conn = conn_find(SVAL(inbuf, smb_tid));
4155 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4159 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4162 if (IS_PRINT(conn)) {
4163 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4166 doff = SVAL(inbuf,smb_vwv11);
4168 numtowrite = SVAL(inbuf,smb_vwv10);
4170 if (len > doff && len - doff > 0xFFFF) {
4171 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4174 if (numtowrite == 0) {
4175 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4179 /* Ensure the sizes match up. */
4180 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4181 /* no pad byte...old smbclient :-( */
4182 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4184 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4188 if (len - doff != numtowrite) {
4189 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4190 "len = %u, doff = %u, numtowrite = %u\n",
4193 (unsigned int)numtowrite ));
4197 DEBUG(10,("is_valid_writeX_buffer: true "
4198 "len = %u, doff = %u, numtowrite = %u\n",
4201 (unsigned int)numtowrite ));
4206 /****************************************************************************
4207 Reply to a write and X.
4208 ****************************************************************************/
4210 void reply_write_and_X(struct smb_request *req)
4212 connection_struct *conn = req->conn;
4214 struct lock_struct lock;
4219 unsigned int smb_doff;
4220 unsigned int smblen;
4224 START_PROFILE(SMBwriteX);
4226 if ((req->wct != 12) && (req->wct != 14)) {
4227 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4228 END_PROFILE(SMBwriteX);
4232 numtowrite = SVAL(req->vwv+10, 0);
4233 smb_doff = SVAL(req->vwv+11, 0);
4234 smblen = smb_len(req->inbuf);
4236 if (req->unread_bytes > 0xFFFF ||
4237 (smblen > smb_doff &&
4238 smblen - smb_doff > 0xFFFF)) {
4239 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4242 if (req->unread_bytes) {
4243 /* Can't do a recvfile write on IPC$ */
4245 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4246 END_PROFILE(SMBwriteX);
4249 if (numtowrite != req->unread_bytes) {
4250 reply_doserror(req, ERRDOS, ERRbadmem);
4251 END_PROFILE(SMBwriteX);
4255 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4256 smb_doff + numtowrite > smblen) {
4257 reply_doserror(req, ERRDOS, ERRbadmem);
4258 END_PROFILE(SMBwriteX);
4263 /* If it's an IPC, pass off the pipe handler. */
4265 if (req->unread_bytes) {
4266 reply_doserror(req, ERRDOS, ERRbadmem);
4267 END_PROFILE(SMBwriteX);
4270 reply_pipe_write_and_X(req);
4271 END_PROFILE(SMBwriteX);
4275 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4276 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4277 write_through = BITSETW(req->vwv+7,0);
4279 if (!check_fsp(conn, req, fsp)) {
4280 END_PROFILE(SMBwriteX);
4284 if (!CHECK_WRITE(fsp)) {
4285 reply_doserror(req, ERRDOS, ERRbadaccess);
4286 END_PROFILE(SMBwriteX);
4290 data = smb_base(req->inbuf) + smb_doff;
4292 if(req->wct == 14) {
4293 #ifdef LARGE_SMB_OFF_T
4295 * This is a large offset (64 bit) write.
4297 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4299 #else /* !LARGE_SMB_OFF_T */
4302 * Ensure we haven't been sent a >32 bit offset.
4305 if(IVAL(req->vwv+12, 0) != 0) {
4306 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4307 "used and we don't support 64 bit offsets.\n",
4308 (unsigned int)IVAL(req->vwv+12, 0) ));
4309 reply_doserror(req, ERRDOS, ERRbadaccess);
4310 END_PROFILE(SMBwriteX);
4314 #endif /* LARGE_SMB_OFF_T */
4317 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4318 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4321 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4322 reply_doserror(req, ERRDOS, ERRlock);
4323 END_PROFILE(SMBwriteX);
4327 /* X/Open SMB protocol says that, unlike SMBwrite
4328 if the length is zero then NO truncation is
4329 done, just a write of zero. To truncate a file,
4332 if(numtowrite == 0) {
4336 if ((req->unread_bytes == 0) &&
4337 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4342 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4345 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4346 reply_unixerror(req, ERRHRD, ERRdiskfull);
4350 reply_outbuf(req, 6, 0);
4351 SSVAL(req->outbuf,smb_vwv2,nwritten);
4352 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4354 if (nwritten < (ssize_t)numtowrite) {
4355 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4356 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4359 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4360 fsp->fnum, (int)numtowrite, (int)nwritten));
4362 status = sync_file(conn, fsp, write_through);
4363 if (!NT_STATUS_IS_OK(status)) {
4364 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4365 fsp->fsp_name, nt_errstr(status) ));
4366 reply_nterror(req, status);
4370 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4372 END_PROFILE(SMBwriteX);
4377 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4379 END_PROFILE(SMBwriteX);
4383 /****************************************************************************
4385 ****************************************************************************/
4387 void reply_lseek(struct smb_request *req)
4389 connection_struct *conn = req->conn;
4395 START_PROFILE(SMBlseek);
4398 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4399 END_PROFILE(SMBlseek);
4403 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4405 if (!check_fsp(conn, req, fsp)) {
4409 flush_write_cache(fsp, SEEK_FLUSH);
4411 mode = SVAL(req->vwv+1, 0) & 3;
4412 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4413 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4422 res = fsp->fh->pos + startpos;
4433 if (umode == SEEK_END) {
4434 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4435 if(errno == EINVAL) {
4436 SMB_OFF_T current_pos = startpos;
4437 SMB_STRUCT_STAT sbuf;
4439 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4440 reply_unixerror(req, ERRDOS,
4442 END_PROFILE(SMBlseek);
4446 current_pos += sbuf.st_ex_size;
4448 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4453 reply_unixerror(req, ERRDOS, ERRnoaccess);
4454 END_PROFILE(SMBlseek);
4461 reply_outbuf(req, 2, 0);
4462 SIVAL(req->outbuf,smb_vwv0,res);
4464 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4465 fsp->fnum, (double)startpos, (double)res, mode));
4467 END_PROFILE(SMBlseek);
4471 /****************************************************************************
4473 ****************************************************************************/
4475 void reply_flush(struct smb_request *req)
4477 connection_struct *conn = req->conn;
4481 START_PROFILE(SMBflush);
4484 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4488 fnum = SVAL(req->vwv+0, 0);
4489 fsp = file_fsp(req, fnum);
4491 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4496 file_sync_all(conn);
4498 NTSTATUS status = sync_file(conn, fsp, True);
4499 if (!NT_STATUS_IS_OK(status)) {
4500 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4501 fsp->fsp_name, nt_errstr(status) ));
4502 reply_nterror(req, status);
4503 END_PROFILE(SMBflush);
4508 reply_outbuf(req, 0, 0);
4510 DEBUG(3,("flush\n"));
4511 END_PROFILE(SMBflush);
4515 /****************************************************************************
4517 conn POINTER CAN BE NULL HERE !
4518 ****************************************************************************/
4520 void reply_exit(struct smb_request *req)
4522 START_PROFILE(SMBexit);
4524 file_close_pid(req->smbpid, req->vuid);
4526 reply_outbuf(req, 0, 0);
4528 DEBUG(3,("exit\n"));
4530 END_PROFILE(SMBexit);
4534 /****************************************************************************
4535 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4536 ****************************************************************************/
4538 void reply_close(struct smb_request *req)
4540 connection_struct *conn = req->conn;
4541 NTSTATUS status = NT_STATUS_OK;
4542 files_struct *fsp = NULL;
4543 START_PROFILE(SMBclose);
4546 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4547 END_PROFILE(SMBclose);
4551 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4554 * We can only use check_fsp if we know it's not a directory.
4557 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4558 reply_doserror(req, ERRDOS, ERRbadfid);
4559 END_PROFILE(SMBclose);
4563 if(fsp->is_directory) {
4565 * Special case - close NT SMB directory handle.
4567 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4568 status = close_file(req, fsp, NORMAL_CLOSE);
4572 * Close ordinary file.
4575 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4576 fsp->fh->fd, fsp->fnum,
4577 conn->num_files_open));
4580 * Take care of any time sent in the close.
4583 t = srv_make_unix_date3(req->vwv+1);
4584 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4587 * close_file() returns the unix errno if an error
4588 * was detected on close - normally this is due to
4589 * a disk full error. If not then it was probably an I/O error.
4592 status = close_file(req, fsp, NORMAL_CLOSE);
4595 if (!NT_STATUS_IS_OK(status)) {
4596 reply_nterror(req, status);
4597 END_PROFILE(SMBclose);
4601 reply_outbuf(req, 0, 0);
4602 END_PROFILE(SMBclose);
4606 /****************************************************************************
4607 Reply to a writeclose (Core+ protocol).
4608 ****************************************************************************/
4610 void reply_writeclose(struct smb_request *req)
4612 connection_struct *conn = req->conn;
4614 ssize_t nwritten = -1;
4615 NTSTATUS close_status = NT_STATUS_OK;
4618 struct timespec mtime;
4620 struct lock_struct lock;
4622 START_PROFILE(SMBwriteclose);
4625 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4626 END_PROFILE(SMBwriteclose);
4630 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4632 if (!check_fsp(conn, req, fsp)) {
4633 END_PROFILE(SMBwriteclose);
4636 if (!CHECK_WRITE(fsp)) {
4637 reply_doserror(req, ERRDOS,ERRbadaccess);
4638 END_PROFILE(SMBwriteclose);
4642 numtowrite = SVAL(req->vwv+1, 0);
4643 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4644 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4645 data = (const char *)req->buf + 1;
4648 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4649 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4652 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4653 reply_doserror(req, ERRDOS,ERRlock);
4654 END_PROFILE(SMBwriteclose);
4659 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4661 set_close_write_time(fsp, mtime);
4664 * More insanity. W2K only closes the file if writelen > 0.
4669 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4671 close_status = close_file(req, fsp, NORMAL_CLOSE);
4674 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4675 fsp->fnum, (int)numtowrite, (int)nwritten,
4676 conn->num_files_open));
4678 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4679 reply_doserror(req, ERRHRD, ERRdiskfull);
4683 if(!NT_STATUS_IS_OK(close_status)) {
4684 reply_nterror(req, close_status);
4688 reply_outbuf(req, 1, 0);
4690 SSVAL(req->outbuf,smb_vwv0,nwritten);
4694 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4697 END_PROFILE(SMBwriteclose);
4702 #define DBGC_CLASS DBGC_LOCKING
4704 /****************************************************************************
4706 ****************************************************************************/
4708 void reply_lock(struct smb_request *req)
4710 connection_struct *conn = req->conn;
4711 uint64_t count,offset;
4714 struct byte_range_lock *br_lck = NULL;
4716 START_PROFILE(SMBlock);
4719 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4720 END_PROFILE(SMBlock);
4724 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4726 if (!check_fsp(conn, req, fsp)) {
4727 END_PROFILE(SMBlock);
4731 count = (uint64_t)IVAL(req->vwv+1, 0);
4732 offset = (uint64_t)IVAL(req->vwv+3, 0);
4734 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4735 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4737 br_lck = do_lock(smbd_messaging_context(),
4744 False, /* Non-blocking lock. */
4749 TALLOC_FREE(br_lck);
4751 if (NT_STATUS_V(status)) {
4752 reply_nterror(req, status);
4753 END_PROFILE(SMBlock);
4757 reply_outbuf(req, 0, 0);
4759 END_PROFILE(SMBlock);
4763 /****************************************************************************
4765 ****************************************************************************/
4767 void reply_unlock(struct smb_request *req)
4769 connection_struct *conn = req->conn;
4770 uint64_t count,offset;
4774 START_PROFILE(SMBunlock);
4777 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4778 END_PROFILE(SMBunlock);
4782 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4784 if (!check_fsp(conn, req, fsp)) {
4785 END_PROFILE(SMBunlock);
4789 count = (uint64_t)IVAL(req->vwv+1, 0);
4790 offset = (uint64_t)IVAL(req->vwv+3, 0);
4792 status = do_unlock(smbd_messaging_context(),
4799 if (NT_STATUS_V(status)) {
4800 reply_nterror(req, status);
4801 END_PROFILE(SMBunlock);
4805 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4806 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4808 reply_outbuf(req, 0, 0);
4810 END_PROFILE(SMBunlock);
4815 #define DBGC_CLASS DBGC_ALL
4817 /****************************************************************************
4819 conn POINTER CAN BE NULL HERE !
4820 ****************************************************************************/
4822 void reply_tdis(struct smb_request *req)
4824 connection_struct *conn = req->conn;
4825 START_PROFILE(SMBtdis);
4828 DEBUG(4,("Invalid connection in tdis\n"));
4829 reply_doserror(req, ERRSRV, ERRinvnid);
4830 END_PROFILE(SMBtdis);
4836 close_cnum(conn,req->vuid);
4839 reply_outbuf(req, 0, 0);
4840 END_PROFILE(SMBtdis);
4844 /****************************************************************************
4846 conn POINTER CAN BE NULL HERE !
4847 ****************************************************************************/
4849 void reply_echo(struct smb_request *req)
4851 connection_struct *conn = req->conn;
4852 struct smb_perfcount_data local_pcd;
4853 struct smb_perfcount_data *cur_pcd;
4857 START_PROFILE(SMBecho);
4859 smb_init_perfcount_data(&local_pcd);
4862 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4863 END_PROFILE(SMBecho);
4867 smb_reverb = SVAL(req->vwv+0, 0);
4869 reply_outbuf(req, 1, req->buflen);
4871 /* copy any incoming data back out */
4872 if (req->buflen > 0) {
4873 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4876 if (smb_reverb > 100) {
4877 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4881 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4883 /* this makes sure we catch the request pcd */
4884 if (seq_num == smb_reverb) {
4885 cur_pcd = &req->pcd;
4887 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4888 cur_pcd = &local_pcd;
4891 SSVAL(req->outbuf,smb_vwv0,seq_num);
4893 show_msg((char *)req->outbuf);
4894 if (!srv_send_smb(smbd_server_fd(),
4895 (char *)req->outbuf,
4896 true, req->seqnum+1,
4897 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4899 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4902 DEBUG(3,("echo %d times\n", smb_reverb));
4904 TALLOC_FREE(req->outbuf);
4906 END_PROFILE(SMBecho);
4910 /****************************************************************************
4911 Reply to a printopen.
4912 ****************************************************************************/
4914 void reply_printopen(struct smb_request *req)
4916 connection_struct *conn = req->conn;
4918 SMB_STRUCT_STAT sbuf;
4921 START_PROFILE(SMBsplopen);
4924 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4925 END_PROFILE(SMBsplopen);
4929 if (!CAN_PRINT(conn)) {
4930 reply_doserror(req, ERRDOS, ERRnoaccess);
4931 END_PROFILE(SMBsplopen);
4935 status = file_new(req, conn, &fsp);
4936 if(!NT_STATUS_IS_OK(status)) {
4937 reply_nterror(req, status);
4938 END_PROFILE(SMBsplopen);
4942 /* Open for exclusive use, write only. */
4943 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4945 if (!NT_STATUS_IS_OK(status)) {
4946 reply_nterror(req, status);
4947 END_PROFILE(SMBsplopen);
4951 reply_outbuf(req, 1, 0);
4952 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4954 DEBUG(3,("openprint fd=%d fnum=%d\n",
4955 fsp->fh->fd, fsp->fnum));
4957 END_PROFILE(SMBsplopen);
4961 /****************************************************************************
4962 Reply to a printclose.
4963 ****************************************************************************/
4965 void reply_printclose(struct smb_request *req)
4967 connection_struct *conn = req->conn;
4971 START_PROFILE(SMBsplclose);
4974 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4975 END_PROFILE(SMBsplclose);
4979 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4981 if (!check_fsp(conn, req, fsp)) {
4982 END_PROFILE(SMBsplclose);
4986 if (!CAN_PRINT(conn)) {
4987 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4988 END_PROFILE(SMBsplclose);
4992 DEBUG(3,("printclose fd=%d fnum=%d\n",
4993 fsp->fh->fd,fsp->fnum));
4995 status = close_file(req, fsp, NORMAL_CLOSE);
4997 if(!NT_STATUS_IS_OK(status)) {
4998 reply_nterror(req, status);
4999 END_PROFILE(SMBsplclose);
5003 reply_outbuf(req, 0, 0);
5005 END_PROFILE(SMBsplclose);
5009 /****************************************************************************
5010 Reply to a printqueue.
5011 ****************************************************************************/
5013 void reply_printqueue(struct smb_request *req)
5015 connection_struct *conn = req->conn;
5019 START_PROFILE(SMBsplretq);
5022 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5023 END_PROFILE(SMBsplretq);
5027 max_count = SVAL(req->vwv+0, 0);
5028 start_index = SVAL(req->vwv+1, 0);
5030 /* we used to allow the client to get the cnum wrong, but that
5031 is really quite gross and only worked when there was only
5032 one printer - I think we should now only accept it if they
5033 get it right (tridge) */
5034 if (!CAN_PRINT(conn)) {
5035 reply_doserror(req, ERRDOS, ERRnoaccess);
5036 END_PROFILE(SMBsplretq);
5040 reply_outbuf(req, 2, 3);
5041 SSVAL(req->outbuf,smb_vwv0,0);
5042 SSVAL(req->outbuf,smb_vwv1,0);
5043 SCVAL(smb_buf(req->outbuf),0,1);
5044 SSVAL(smb_buf(req->outbuf),1,0);
5046 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5047 start_index, max_count));
5050 print_queue_struct *queue = NULL;
5051 print_status_struct status;
5052 int count = print_queue_status(SNUM(conn), &queue, &status);
5053 int num_to_get = ABS(max_count);
5054 int first = (max_count>0?start_index:start_index+max_count+1);
5060 num_to_get = MIN(num_to_get,count-first);
5063 for (i=first;i<first+num_to_get;i++) {
5067 srv_put_dos_date2(p,0,queue[i].time);
5068 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5069 SSVAL(p,5, queue[i].job);
5070 SIVAL(p,7,queue[i].size);
5072 srvstr_push(blob, req->flags2, p+12,
5073 queue[i].fs_user, 16, STR_ASCII);
5075 if (message_push_blob(
5078 blob, sizeof(blob))) == -1) {
5079 reply_nterror(req, NT_STATUS_NO_MEMORY);
5080 END_PROFILE(SMBsplretq);
5086 SSVAL(req->outbuf,smb_vwv0,count);
5087 SSVAL(req->outbuf,smb_vwv1,
5088 (max_count>0?first+count:first-1));
5089 SCVAL(smb_buf(req->outbuf),0,1);
5090 SSVAL(smb_buf(req->outbuf),1,28*count);
5095 DEBUG(3,("%d entries returned in queue\n",count));
5098 END_PROFILE(SMBsplretq);
5102 /****************************************************************************
5103 Reply to a printwrite.
5104 ****************************************************************************/
5106 void reply_printwrite(struct smb_request *req)
5108 connection_struct *conn = req->conn;
5113 START_PROFILE(SMBsplwr);
5116 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5117 END_PROFILE(SMBsplwr);
5121 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5123 if (!check_fsp(conn, req, fsp)) {
5124 END_PROFILE(SMBsplwr);
5128 if (!CAN_PRINT(conn)) {
5129 reply_doserror(req, ERRDOS, ERRnoaccess);
5130 END_PROFILE(SMBsplwr);
5134 if (!CHECK_WRITE(fsp)) {
5135 reply_doserror(req, ERRDOS, ERRbadaccess);
5136 END_PROFILE(SMBsplwr);
5140 numtowrite = SVAL(req->buf, 1);
5142 if (req->buflen < numtowrite + 3) {
5143 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5144 END_PROFILE(SMBsplwr);
5148 data = (const char *)req->buf + 3;
5150 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5151 reply_unixerror(req, ERRHRD, ERRdiskfull);
5152 END_PROFILE(SMBsplwr);
5156 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5158 END_PROFILE(SMBsplwr);
5162 /****************************************************************************
5164 ****************************************************************************/
5166 void reply_mkdir(struct smb_request *req)
5168 connection_struct *conn = req->conn;
5169 struct smb_filename *smb_dname = NULL;
5170 char *directory = NULL;
5172 TALLOC_CTX *ctx = talloc_tos();
5174 START_PROFILE(SMBmkdir);
5176 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5177 STR_TERMINATE, &status);
5178 if (!NT_STATUS_IS_OK(status)) {
5179 reply_nterror(req, status);
5183 status = resolve_dfspath(ctx, conn,
5184 req->flags2 & FLAGS2_DFS_PATHNAMES,
5187 if (!NT_STATUS_IS_OK(status)) {
5188 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5189 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5190 ERRSRV, ERRbadpath);
5193 reply_nterror(req, status);
5197 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
5198 if (!NT_STATUS_IS_OK(status)) {
5199 reply_nterror(req, status);
5203 status = get_full_smb_filename(ctx, smb_dname, &directory);
5204 if (!NT_STATUS_IS_OK(status)) {
5205 reply_nterror(req, status);
5209 status = check_name(conn, directory);
5210 if (!NT_STATUS_IS_OK(status)) {
5211 reply_nterror(req, status);
5215 status = create_directory(conn, req, directory);
5217 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5219 if (!NT_STATUS_IS_OK(status)) {
5221 if (!use_nt_status()
5222 && NT_STATUS_EQUAL(status,
5223 NT_STATUS_OBJECT_NAME_COLLISION)) {
5225 * Yes, in the DOS error code case we get a
5226 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5227 * samba4 torture test.
5229 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5232 reply_nterror(req, status);
5236 reply_outbuf(req, 0, 0);
5238 DEBUG( 3, ( "mkdir %s\n", directory ) );
5240 TALLOC_FREE(smb_dname);
5241 END_PROFILE(SMBmkdir);
5245 /****************************************************************************
5246 Static function used by reply_rmdir to delete an entire directory
5247 tree recursively. Return True on ok, False on fail.
5248 ****************************************************************************/
5250 static bool recursive_rmdir(TALLOC_CTX *ctx,
5251 connection_struct *conn,
5254 const char *dname = NULL;
5258 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5264 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5265 char *fullname = NULL;
5267 if (ISDOT(dname) || ISDOTDOT(dname)) {
5271 if (!is_visible_file(conn, directory, dname, &st, False)) {
5275 /* Construct the full name. */
5276 fullname = talloc_asprintf(ctx,
5286 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5291 if(st.st_ex_mode & S_IFDIR) {
5292 if(!recursive_rmdir(ctx, conn, fullname)) {
5296 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5300 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5304 TALLOC_FREE(fullname);
5306 TALLOC_FREE(dir_hnd);
5310 /****************************************************************************
5311 The internals of the rmdir code - called elsewhere.
5312 ****************************************************************************/
5314 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5315 connection_struct *conn,
5316 const char *directory)
5321 /* Might be a symlink. */
5322 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5323 return map_nt_error_from_unix(errno);
5326 if (S_ISLNK(st.st_ex_mode)) {
5327 /* Is what it points to a directory ? */
5328 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5329 return map_nt_error_from_unix(errno);
5331 if (!(S_ISDIR(st.st_ex_mode))) {
5332 return NT_STATUS_NOT_A_DIRECTORY;
5334 ret = SMB_VFS_UNLINK(conn,directory);
5336 ret = SMB_VFS_RMDIR(conn,directory);
5339 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5340 FILE_NOTIFY_CHANGE_DIR_NAME,
5342 return NT_STATUS_OK;
5345 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5347 * Check to see if the only thing in this directory are
5348 * vetoed files/directories. If so then delete them and
5349 * retry. If we fail to delete any of them (and we *don't*
5350 * do a recursive delete) then fail the rmdir.
5354 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5355 directory, NULL, 0);
5357 if(dir_hnd == NULL) {
5362 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5363 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5365 if (!is_visible_file(conn, directory, dname, &st, False))
5367 if(!IS_VETO_PATH(conn, dname)) {
5368 TALLOC_FREE(dir_hnd);
5374 /* We only have veto files/directories.
5375 * Are we allowed to delete them ? */
5377 if(!lp_recursive_veto_delete(SNUM(conn))) {
5378 TALLOC_FREE(dir_hnd);
5383 /* Do a recursive delete. */
5384 RewindDir(dir_hnd,&dirpos);
5385 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5386 char *fullname = NULL;
5388 if (ISDOT(dname) || ISDOTDOT(dname)) {
5391 if (!is_visible_file(conn, directory, dname, &st, False)) {
5395 fullname = talloc_asprintf(ctx,
5405 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5408 if(st.st_ex_mode & S_IFDIR) {
5409 if(!recursive_rmdir(ctx, conn, fullname)) {
5412 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5415 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5418 TALLOC_FREE(fullname);
5420 TALLOC_FREE(dir_hnd);
5421 /* Retry the rmdir */
5422 ret = SMB_VFS_RMDIR(conn,directory);
5428 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5429 "%s\n", directory,strerror(errno)));
5430 return map_nt_error_from_unix(errno);
5433 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5434 FILE_NOTIFY_CHANGE_DIR_NAME,
5437 return NT_STATUS_OK;
5440 /****************************************************************************
5442 ****************************************************************************/
5444 void reply_rmdir(struct smb_request *req)
5446 connection_struct *conn = req->conn;
5447 struct smb_filename *smb_dname = NULL;
5448 char *directory = NULL;
5450 TALLOC_CTX *ctx = talloc_tos();
5452 START_PROFILE(SMBrmdir);
5454 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5455 STR_TERMINATE, &status);
5456 if (!NT_STATUS_IS_OK(status)) {
5457 reply_nterror(req, status);
5461 status = resolve_dfspath(ctx, conn,
5462 req->flags2 & FLAGS2_DFS_PATHNAMES,
5465 if (!NT_STATUS_IS_OK(status)) {
5466 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5467 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5468 ERRSRV, ERRbadpath);
5471 reply_nterror(req, status);
5475 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
5476 if (!NT_STATUS_IS_OK(status)) {
5477 reply_nterror(req, status);
5481 status = get_full_smb_filename(ctx, smb_dname, &directory);
5482 if (!NT_STATUS_IS_OK(status)) {
5483 reply_nterror(req, status);
5487 status = check_name(conn, directory);
5488 if (!NT_STATUS_IS_OK(status)) {
5489 reply_nterror(req, status);
5493 dptr_closepath(directory, req->smbpid);
5494 status = rmdir_internals(ctx, conn, directory);
5495 if (!NT_STATUS_IS_OK(status)) {
5496 reply_nterror(req, status);
5500 reply_outbuf(req, 0, 0);
5502 DEBUG( 3, ( "rmdir %s\n", directory ) );
5504 TALLOC_FREE(smb_dname);
5505 END_PROFILE(SMBrmdir);
5509 /*******************************************************************
5510 Resolve wildcards in a filename rename.
5511 ********************************************************************/
5513 static bool resolve_wildcards(TALLOC_CTX *ctx,
5518 char *name2_copy = NULL;
5523 char *p,*p2, *pname1, *pname2;
5525 name2_copy = talloc_strdup(ctx, name2);
5530 pname1 = strrchr_m(name1,'/');
5531 pname2 = strrchr_m(name2_copy,'/');
5533 if (!pname1 || !pname2) {
5537 /* Truncate the copy of name2 at the last '/' */
5540 /* Now go past the '/' */
5544 root1 = talloc_strdup(ctx, pname1);
5545 root2 = talloc_strdup(ctx, pname2);
5547 if (!root1 || !root2) {
5551 p = strrchr_m(root1,'.');
5554 ext1 = talloc_strdup(ctx, p+1);
5556 ext1 = talloc_strdup(ctx, "");
5558 p = strrchr_m(root2,'.');
5561 ext2 = talloc_strdup(ctx, p+1);
5563 ext2 = talloc_strdup(ctx, "");
5566 if (!ext1 || !ext2) {
5574 /* Hmmm. Should this be mb-aware ? */
5577 } else if (*p2 == '*') {
5579 root2 = talloc_asprintf(ctx, "%s%s",
5598 /* Hmmm. Should this be mb-aware ? */
5601 } else if (*p2 == '*') {
5603 ext2 = talloc_asprintf(ctx, "%s%s",
5619 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5624 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5636 /****************************************************************************
5637 Ensure open files have their names updated. Updated to notify other smbd's
5639 ****************************************************************************/
5641 static void rename_open_files(connection_struct *conn,
5642 struct share_mode_lock *lck,
5643 const char *newname)
5646 bool did_rename = False;
5648 for(fsp = file_find_di_first(lck->id); fsp;
5649 fsp = file_find_di_next(fsp)) {
5650 /* fsp_name is a relative path under the fsp. To change this for other
5651 sharepaths we need to manipulate relative paths. */
5652 /* TODO - create the absolute path and manipulate the newname
5653 relative to the sharepath. */
5654 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5657 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5658 fsp->fnum, file_id_string_tos(&fsp->file_id),
5659 fsp->fsp_name, newname ));
5660 string_set(&fsp->fsp_name, newname);
5665 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5666 file_id_string_tos(&lck->id), newname ));
5669 /* Send messages to all smbd's (not ourself) that the name has changed. */
5670 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5674 /****************************************************************************
5675 We need to check if the source path is a parent directory of the destination
5676 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5677 refuse the rename with a sharing violation. Under UNIX the above call can
5678 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5679 probably need to check that the client is a Windows one before disallowing
5680 this as a UNIX client (one with UNIX extensions) can know the source is a
5681 symlink and make this decision intelligently. Found by an excellent bug
5682 report from <AndyLiebman@aol.com>.
5683 ****************************************************************************/
5685 static bool rename_path_prefix_equal(const char *src, const char *dest)
5687 const char *psrc = src;
5688 const char *pdst = dest;
5691 if (psrc[0] == '.' && psrc[1] == '/') {
5694 if (pdst[0] == '.' && pdst[1] == '/') {
5697 if ((slen = strlen(psrc)) > strlen(pdst)) {
5700 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5704 * Do the notify calls from a rename
5707 static void notify_rename(connection_struct *conn, bool is_dir,
5708 const char *oldpath, const char *newpath)
5710 char *olddir, *newdir;
5711 const char *oldname, *newname;
5714 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5715 : FILE_NOTIFY_CHANGE_FILE_NAME;
5717 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5718 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5719 TALLOC_FREE(olddir);
5723 if (strcmp(olddir, newdir) == 0) {
5724 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5725 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5728 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5729 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5731 TALLOC_FREE(olddir);
5732 TALLOC_FREE(newdir);
5734 /* this is a strange one. w2k3 gives an additional event for
5735 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5736 files, but not directories */
5738 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5739 FILE_NOTIFY_CHANGE_ATTRIBUTES
5740 |FILE_NOTIFY_CHANGE_CREATION,
5745 /****************************************************************************
5746 Rename an open file - given an fsp.
5747 ****************************************************************************/
5749 NTSTATUS rename_internals_fsp(connection_struct *conn,
5752 const char *newname_last_component,
5754 bool replace_if_exists)
5756 TALLOC_CTX *ctx = talloc_tos();
5757 SMB_STRUCT_STAT sbuf, sbuf1;
5758 NTSTATUS status = NT_STATUS_OK;
5759 struct share_mode_lock *lck = NULL;
5760 bool dst_exists, old_is_stream, new_is_stream;
5764 status = check_name(conn, newname);
5765 if (!NT_STATUS_IS_OK(status)) {
5769 /* Ensure newname contains a '/' */
5770 if(strrchr_m(newname,'/') == 0) {
5771 newname = talloc_asprintf(ctx,
5775 return NT_STATUS_NO_MEMORY;
5780 * Check for special case with case preserving and not
5781 * case sensitive. If the old last component differs from the original
5782 * last component only by case, then we should allow
5783 * the rename (user is trying to change the case of the
5787 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5788 strequal(newname, fsp->fsp_name)) {
5790 char *newname_modified_last_component = NULL;
5793 * Get the last component of the modified name.
5794 * Note that we guarantee that newname contains a '/'
5797 p = strrchr_m(newname,'/');
5798 newname_modified_last_component = talloc_strdup(ctx,
5800 if (!newname_modified_last_component) {
5801 return NT_STATUS_NO_MEMORY;
5804 if(strcsequal(newname_modified_last_component,
5805 newname_last_component) == False) {
5807 * Replace the modified last component with
5810 *p = '\0'; /* Truncate at the '/' */
5811 newname = talloc_asprintf(ctx,
5814 newname_last_component);
5819 * If the src and dest names are identical - including case,
5820 * don't do the rename, just return success.
5823 if (strcsequal(fsp->fsp_name, newname)) {
5824 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5826 return NT_STATUS_OK;
5829 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5830 new_is_stream = is_ntfs_stream_name(newname);
5832 /* Return the correct error code if both names aren't streams. */
5833 if (!old_is_stream && new_is_stream) {
5834 return NT_STATUS_OBJECT_NAME_INVALID;
5837 if (old_is_stream && !new_is_stream) {
5838 return NT_STATUS_INVALID_PARAMETER;
5842 * Have vfs_object_exist also fill sbuf1
5844 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5846 if(!replace_if_exists && dst_exists) {
5847 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5848 fsp->fsp_name,newname));
5849 return NT_STATUS_OBJECT_NAME_COLLISION;
5853 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5854 files_struct *dst_fsp = file_find_di_first(fileid);
5855 /* The file can be open when renaming a stream */
5856 if (dst_fsp && !new_is_stream) {
5857 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5858 return NT_STATUS_ACCESS_DENIED;
5862 /* Ensure we have a valid stat struct for the source. */
5863 if (fsp->fh->fd != -1) {
5864 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5865 return map_nt_error_from_unix(errno);
5869 if (fsp->posix_open) {
5870 ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
5872 ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
5875 return map_nt_error_from_unix(errno);
5879 status = can_rename(conn, fsp, attrs, &sbuf);
5881 if (!NT_STATUS_IS_OK(status)) {
5882 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5883 nt_errstr(status), fsp->fsp_name,newname));
5884 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5885 status = NT_STATUS_ACCESS_DENIED;
5889 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5890 return NT_STATUS_ACCESS_DENIED;
5893 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5897 * We have the file open ourselves, so not being able to get the
5898 * corresponding share mode lock is a fatal error.
5901 SMB_ASSERT(lck != NULL);
5903 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5904 uint32 create_options = fsp->fh->private_options;
5906 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5907 fsp->fsp_name,newname));
5909 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5911 rename_open_files(conn, lck, newname);
5914 * A rename acts as a new file create w.r.t. allowing an initial delete
5915 * on close, probably because in Windows there is a new handle to the
5916 * new file. If initial delete on close was requested but not
5917 * originally set, we need to set it here. This is probably not 100% correct,
5918 * but will work for the CIFSFS client which in non-posix mode
5919 * depends on these semantics. JRA.
5922 if (create_options & FILE_DELETE_ON_CLOSE) {
5923 status = can_set_delete_on_close(fsp, True, 0);
5925 if (NT_STATUS_IS_OK(status)) {
5926 /* Note that here we set the *inital* delete on close flag,
5927 * not the regular one. The magic gets handled in close. */
5928 fsp->initial_delete_on_close = True;
5932 return NT_STATUS_OK;
5937 if (errno == ENOTDIR || errno == EISDIR) {
5938 status = NT_STATUS_OBJECT_NAME_COLLISION;
5940 status = map_nt_error_from_unix(errno);
5943 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5944 nt_errstr(status), fsp->fsp_name,newname));
5949 /****************************************************************************
5950 The guts of the rename command, split out so it may be called by the NT SMB
5952 ****************************************************************************/
5954 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5955 connection_struct *conn,
5956 struct smb_request *req,
5957 const char *name_in,
5958 const char *newname_in,
5960 bool replace_if_exists,
5963 uint32_t access_mask)
5965 struct smb_filename *smb_fname = NULL;
5966 struct smb_filename *smb_fname_new = NULL;
5967 char *directory = NULL;
5970 char *newname = NULL;
5973 NTSTATUS status = NT_STATUS_OK;
5974 struct smb_Dir *dir_hnd = NULL;
5977 int create_options = 0;
5978 bool posix_pathnames = lp_posix_pathnames();
5980 status = unix_convert(ctx, conn, name_in, &smb_fname,
5981 src_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
5982 if (!NT_STATUS_IS_OK(status)) {
5986 status = get_full_smb_filename(ctx, smb_fname, &name);
5987 if (!NT_STATUS_IS_OK(status)) {
5991 status = unix_convert(ctx, conn, newname_in, &smb_fname_new,
5993 (dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0)));
5994 if (!NT_STATUS_IS_OK(status)) {
5998 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
5999 if (!NT_STATUS_IS_OK(status)) {
6004 * Split the old name into directory and last component
6005 * strings. Note that unix_convert may have stripped off a
6006 * leading ./ from both name and newname if the rename is
6007 * at the root of the share. We need to make sure either both
6008 * name and newname contain a / character or neither of them do
6009 * as this is checked in resolve_wildcards().
6012 p = strrchr_m(name,'/');
6014 directory = talloc_strdup(ctx, ".");
6016 status = NT_STATUS_NO_MEMORY;
6022 directory = talloc_strdup(ctx, name);
6024 status = NT_STATUS_NO_MEMORY;
6028 *p = '/'; /* Replace needed for exceptional test below. */
6032 * We should only check the mangled cache
6033 * here if unix_convert failed. This means
6034 * that the path in 'mask' doesn't exist
6035 * on the file system and so we need to look
6036 * for a possible mangle. This patch from
6037 * Tine Smukavec <valentin.smukavec@hermes.si>.
6040 if (!VALID_STAT(smb_fname->st) && mangle_is_mangled(mask, conn->params)) {
6041 char *new_mask = NULL;
6042 mangle_lookup_name_from_8_3(ctx,
6051 if (!src_has_wild) {
6055 * No wildcards - just process the one file.
6057 /* Add a terminating '/' to the directory name. */
6058 directory = talloc_asprintf_append(directory,
6062 status = NT_STATUS_NO_MEMORY;
6066 /* Ensure newname contains a '/' also */
6067 if(strrchr_m(newname,'/') == 0) {
6068 newname = talloc_asprintf(ctx,
6072 status = NT_STATUS_NO_MEMORY;
6077 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6078 "case_preserve = %d, short case preserve = %d, "
6079 "directory = %s, newname = %s, "
6080 "last_component_dest = %s\n",
6081 conn->case_sensitive, conn->case_preserve,
6082 conn->short_case_preserve, directory,
6083 newname, smb_fname_new->original_lcomp));
6085 /* The dest name still may have wildcards. */
6086 if (dest_has_wild) {
6087 char *mod_newname = NULL;
6088 if (!resolve_wildcards(ctx,
6089 directory,newname,&mod_newname)) {
6090 DEBUG(6, ("rename_internals: resolve_wildcards "
6094 status = NT_STATUS_NO_MEMORY;
6097 newname = mod_newname;
6100 ZERO_STRUCT(smb_fname->st);
6101 if (posix_pathnames) {
6102 SMB_VFS_LSTAT(conn, directory, &smb_fname->st);
6104 SMB_VFS_STAT(conn, directory, &smb_fname->st);
6107 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6108 create_options |= FILE_DIRECTORY_FILE;
6111 status = SMB_VFS_CREATE_FILE(
6114 0, /* root_dir_fid */
6115 directory, /* fname */
6116 0, /* create_file_flags */
6117 access_mask, /* access_mask */
6118 (FILE_SHARE_READ | /* share_access */
6120 FILE_OPEN, /* create_disposition*/
6121 create_options, /* create_options */
6122 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6123 0, /* oplock_request */
6124 0, /* allocation_size */
6129 &smb_fname->st); /* psbuf */
6131 if (!NT_STATUS_IS_OK(status)) {
6132 DEBUG(3, ("Could not open rename source %s: %s\n",
6133 directory, nt_errstr(status)));
6137 status = rename_internals_fsp(conn, fsp, newname,
6138 smb_fname_new->original_lcomp,
6139 attrs, replace_if_exists);
6141 close_file(req, fsp, NORMAL_CLOSE);
6143 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6144 nt_errstr(status), directory,newname));
6150 * Wildcards - process each file that matches.
6152 if (strequal(mask,"????????.???")) {
6157 status = check_name(conn, directory);
6158 if (!NT_STATUS_IS_OK(status)) {
6162 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
6163 if (dir_hnd == NULL) {
6164 status = map_nt_error_from_unix(errno);
6168 status = NT_STATUS_NO_SUCH_FILE;
6170 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6171 * - gentest fix. JRA
6174 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname->st))) {
6175 files_struct *fsp = NULL;
6177 char *destname = NULL;
6178 bool sysdir_entry = False;
6180 /* Quick check for "." and ".." */
6181 if (ISDOT(dname) || ISDOTDOT(dname)) {
6183 sysdir_entry = True;
6189 if (!is_visible_file(conn, directory, dname, &smb_fname->st,
6194 if(!mask_match(dname, mask, conn->case_sensitive)) {
6199 status = NT_STATUS_OBJECT_NAME_INVALID;
6203 fname = talloc_asprintf(ctx,
6208 status = NT_STATUS_NO_MEMORY;
6212 if (!resolve_wildcards(ctx,
6213 fname,newname,&destname)) {
6214 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6220 status = NT_STATUS_NO_MEMORY;
6224 ZERO_STRUCT(smb_fname->st);
6225 if (posix_pathnames) {
6226 SMB_VFS_LSTAT(conn, fname, &smb_fname->st);
6228 SMB_VFS_STAT(conn, fname, &smb_fname->st);
6233 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6234 create_options |= FILE_DIRECTORY_FILE;
6237 status = SMB_VFS_CREATE_FILE(
6240 0, /* root_dir_fid */
6242 0, /* create_file_flags */
6243 access_mask, /* access_mask */
6244 (FILE_SHARE_READ | /* share_access */
6246 FILE_OPEN, /* create_disposition*/
6247 create_options, /* create_options */
6248 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6249 0, /* oplock_request */
6250 0, /* allocation_size */
6255 &smb_fname->st); /* psbuf */
6257 if (!NT_STATUS_IS_OK(status)) {
6258 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6259 "returned %s rename %s -> %s\n",
6260 nt_errstr(status), directory, newname));
6264 status = rename_internals_fsp(conn, fsp, destname, dname,
6265 attrs, replace_if_exists);
6267 close_file(req, fsp, NORMAL_CLOSE);
6269 if (!NT_STATUS_IS_OK(status)) {
6270 DEBUG(3, ("rename_internals_fsp returned %s for "
6271 "rename %s -> %s\n", nt_errstr(status),
6272 directory, newname));
6278 DEBUG(3,("rename_internals: doing rename on %s -> "
6279 "%s\n",fname,destname));
6282 TALLOC_FREE(destname);
6284 TALLOC_FREE(dir_hnd);
6286 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6287 status = map_nt_error_from_unix(errno);
6291 TALLOC_FREE(smb_fname);
6292 TALLOC_FREE(smb_fname_new);
6296 /****************************************************************************
6298 ****************************************************************************/
6300 void reply_mv(struct smb_request *req)
6302 connection_struct *conn = req->conn;
6304 char *newname = NULL;
6308 bool src_has_wcard = False;
6309 bool dest_has_wcard = False;
6310 TALLOC_CTX *ctx = talloc_tos();
6312 START_PROFILE(SMBmv);
6315 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6320 attrs = SVAL(req->vwv+0, 0);
6322 p = (const char *)req->buf + 1;
6323 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6324 &status, &src_has_wcard);
6325 if (!NT_STATUS_IS_OK(status)) {
6326 reply_nterror(req, status);
6331 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6332 &status, &dest_has_wcard);
6333 if (!NT_STATUS_IS_OK(status)) {
6334 reply_nterror(req, status);
6339 status = resolve_dfspath_wcard(ctx, conn,
6340 req->flags2 & FLAGS2_DFS_PATHNAMES,
6344 if (!NT_STATUS_IS_OK(status)) {
6345 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6346 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6347 ERRSRV, ERRbadpath);
6351 reply_nterror(req, status);
6356 status = resolve_dfspath_wcard(ctx, conn,
6357 req->flags2 & FLAGS2_DFS_PATHNAMES,
6361 if (!NT_STATUS_IS_OK(status)) {
6362 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6363 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6364 ERRSRV, ERRbadpath);
6368 reply_nterror(req, status);
6373 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6375 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6376 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6377 if (!NT_STATUS_IS_OK(status)) {
6378 if (open_was_deferred(req->mid)) {
6379 /* We have re-scheduled this call. */
6383 reply_nterror(req, status);
6388 reply_outbuf(req, 0, 0);
6394 /*******************************************************************
6395 Copy a file as part of a reply_copy.
6396 ******************************************************************/
6399 * TODO: check error codes on all callers
6402 NTSTATUS copy_file(TALLOC_CTX *ctx,
6403 connection_struct *conn,
6408 bool target_is_directory)
6410 SMB_STRUCT_STAT src_sbuf, sbuf2;
6412 files_struct *fsp1,*fsp2;
6415 uint32 new_create_disposition;
6418 dest = talloc_strdup(ctx, dest1);
6420 return NT_STATUS_NO_MEMORY;
6422 if (target_is_directory) {
6423 const char *p = strrchr_m(src,'/');
6429 dest = talloc_asprintf_append(dest,
6433 return NT_STATUS_NO_MEMORY;
6437 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6439 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6442 if (!target_is_directory && count) {
6443 new_create_disposition = FILE_OPEN;
6445 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6446 NULL, NULL, &new_create_disposition, NULL)) {
6448 return NT_STATUS_INVALID_PARAMETER;
6452 status = SMB_VFS_CREATE_FILE(
6455 0, /* root_dir_fid */
6457 0, /* create_file_flags */
6458 FILE_GENERIC_READ, /* access_mask */
6459 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6460 FILE_OPEN, /* create_disposition*/
6461 0, /* create_options */
6462 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6463 INTERNAL_OPEN_ONLY, /* oplock_request */
6464 0, /* allocation_size */
6469 &src_sbuf); /* psbuf */
6471 if (!NT_STATUS_IS_OK(status)) {
6476 dosattrs = dos_mode(conn, src, &src_sbuf);
6477 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6478 ZERO_STRUCTP(&sbuf2);
6481 status = SMB_VFS_CREATE_FILE(
6484 0, /* root_dir_fid */
6486 0, /* create_file_flags */
6487 FILE_GENERIC_WRITE, /* access_mask */
6488 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6489 new_create_disposition, /* create_disposition*/
6490 0, /* create_options */
6491 dosattrs, /* file_attributes */
6492 INTERNAL_OPEN_ONLY, /* oplock_request */
6493 0, /* allocation_size */
6498 &sbuf2); /* psbuf */
6502 if (!NT_STATUS_IS_OK(status)) {
6503 close_file(NULL, fsp1, ERROR_CLOSE);
6507 if ((ofun&3) == 1) {
6508 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6509 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6511 * Stop the copy from occurring.
6514 src_sbuf.st_ex_size = 0;
6518 if (src_sbuf.st_ex_size) {
6519 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_ex_size);
6522 close_file(NULL, fsp1, NORMAL_CLOSE);
6524 /* Ensure the modtime is set correctly on the destination file. */
6525 set_close_write_time(fsp2, src_sbuf.st_ex_mtime);
6528 * As we are opening fsp1 read-only we only expect
6529 * an error on close on fsp2 if we are out of space.
6530 * Thus we don't look at the error return from the
6533 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6535 if (!NT_STATUS_IS_OK(status)) {
6539 if (ret != (SMB_OFF_T)src_sbuf.st_ex_size) {
6540 return NT_STATUS_DISK_FULL;
6543 return NT_STATUS_OK;
6546 /****************************************************************************
6547 Reply to a file copy.
6548 ****************************************************************************/
6550 void reply_copy(struct smb_request *req)
6552 connection_struct *conn = req->conn;
6553 struct smb_filename *smb_fname = NULL;
6554 struct smb_filename *smb_fname_new = NULL;
6556 char *newname = NULL;
6557 char *directory = NULL;
6558 const char *mask = NULL;
6559 const char mask_star[] = "*";
6562 int error = ERRnoaccess;
6567 bool target_is_directory=False;
6568 bool source_has_wild = False;
6569 bool dest_has_wild = False;
6571 TALLOC_CTX *ctx = talloc_tos();
6573 START_PROFILE(SMBcopy);
6576 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6580 tid2 = SVAL(req->vwv+0, 0);
6581 ofun = SVAL(req->vwv+1, 0);
6582 flags = SVAL(req->vwv+2, 0);
6584 p = (const char *)req->buf;
6585 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6586 &status, &source_has_wild);
6587 if (!NT_STATUS_IS_OK(status)) {
6588 reply_nterror(req, status);
6591 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6592 &status, &dest_has_wild);
6593 if (!NT_STATUS_IS_OK(status)) {
6594 reply_nterror(req, status);
6598 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6600 if (tid2 != conn->cnum) {
6601 /* can't currently handle inter share copies XXXX */
6602 DEBUG(3,("Rejecting inter-share copy\n"));
6603 reply_doserror(req, ERRSRV, ERRinvdevice);
6607 status = resolve_dfspath_wcard(ctx, conn,
6608 req->flags2 & FLAGS2_DFS_PATHNAMES,
6612 if (!NT_STATUS_IS_OK(status)) {
6613 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6614 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6615 ERRSRV, ERRbadpath);
6618 reply_nterror(req, status);
6622 status = resolve_dfspath_wcard(ctx, conn,
6623 req->flags2 & FLAGS2_DFS_PATHNAMES,
6627 if (!NT_STATUS_IS_OK(status)) {
6628 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6629 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6630 ERRSRV, ERRbadpath);
6633 reply_nterror(req, status);
6637 status = unix_convert(ctx, conn, name, &smb_fname,
6638 source_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6639 if (!NT_STATUS_IS_OK(status)) {
6640 reply_nterror(req, status);
6644 status = get_full_smb_filename(ctx, smb_fname, &name);
6645 if (!NT_STATUS_IS_OK(status)) {
6646 reply_nterror(req, status);
6650 status = unix_convert(ctx, conn, newname, &smb_fname_new,
6651 dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6652 if (!NT_STATUS_IS_OK(status)) {
6653 reply_nterror(req, status);
6657 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
6658 if (!NT_STATUS_IS_OK(status)) {
6659 reply_nterror(req, status);
6663 target_is_directory = VALID_STAT_OF_DIR(smb_fname_new->st);
6665 if ((flags&1) && target_is_directory) {
6666 reply_doserror(req, ERRDOS, ERRbadfile);
6670 if ((flags&2) && !target_is_directory) {
6671 reply_doserror(req, ERRDOS, ERRbadpath);
6675 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname->st)) {
6676 /* wants a tree copy! XXXX */
6677 DEBUG(3,("Rejecting tree copy\n"));
6678 reply_doserror(req, ERRSRV, ERRerror);
6682 p = strrchr_m(name,'/');
6684 directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
6687 directory = talloc_strdup(ctx, "./");
6692 reply_nterror(req, NT_STATUS_NO_MEMORY);
6697 * We should only check the mangled cache
6698 * here if unix_convert failed. This means
6699 * that the path in 'mask' doesn't exist
6700 * on the file system and so we need to look
6701 * for a possible mangle. This patch from
6702 * Tine Smukavec <valentin.smukavec@hermes.si>.
6705 if (!VALID_STAT(smb_fname->st) &&
6706 mangle_is_mangled(mask, conn->params)) {
6707 char *new_mask = NULL;
6708 mangle_lookup_name_from_8_3(ctx,
6717 if (!source_has_wild) {
6718 directory = talloc_asprintf_append(directory,
6721 if (dest_has_wild) {
6722 char *mod_newname = NULL;
6723 if (!resolve_wildcards(ctx,
6724 directory,newname,&mod_newname)) {
6725 reply_nterror(req, NT_STATUS_NO_MEMORY);
6728 newname = mod_newname;
6731 status = check_name(conn, directory);
6732 if (!NT_STATUS_IS_OK(status)) {
6733 reply_nterror(req, status);
6737 status = check_name(conn, newname);
6738 if (!NT_STATUS_IS_OK(status)) {
6739 reply_nterror(req, status);
6743 status = copy_file(ctx,conn,directory,newname,ofun,
6744 count,target_is_directory);
6746 if(!NT_STATUS_IS_OK(status)) {
6747 reply_nterror(req, status);
6753 struct smb_Dir *dir_hnd = NULL;
6754 const char *dname = NULL;
6757 if (strequal(mask,"????????.???")) {
6761 status = check_name(conn, directory);
6762 if (!NT_STATUS_IS_OK(status)) {
6763 reply_nterror(req, status);
6767 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6768 if (dir_hnd == NULL) {
6769 status = map_nt_error_from_unix(errno);
6770 reply_nterror(req, status);
6776 while ((dname = ReadDirName(dir_hnd, &offset,
6778 char *destname = NULL;
6781 if (ISDOT(dname) || ISDOTDOT(dname)) {
6785 if (!is_visible_file(conn, directory, dname,
6786 &smb_fname->st, False)) {
6790 if(!mask_match(dname, mask, conn->case_sensitive)) {
6794 error = ERRnoaccess;
6795 fname = talloc_asprintf(ctx,
6800 TALLOC_FREE(dir_hnd);
6801 reply_nterror(req, NT_STATUS_NO_MEMORY);
6805 if (!resolve_wildcards(ctx,
6806 fname,newname,&destname)) {
6810 TALLOC_FREE(dir_hnd);
6811 reply_nterror(req, NT_STATUS_NO_MEMORY);
6815 status = check_name(conn, fname);
6816 if (!NT_STATUS_IS_OK(status)) {
6817 TALLOC_FREE(dir_hnd);
6818 reply_nterror(req, status);
6822 status = check_name(conn, destname);
6823 if (!NT_STATUS_IS_OK(status)) {
6824 TALLOC_FREE(dir_hnd);
6825 reply_nterror(req, status);
6829 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6831 status = copy_file(ctx,conn,fname,destname,ofun,
6832 count,target_is_directory);
6833 if (NT_STATUS_IS_OK(status)) {
6837 TALLOC_FREE(destname);
6839 TALLOC_FREE(dir_hnd);
6844 /* Error on close... */
6846 reply_unixerror(req, ERRHRD, ERRgeneral);
6850 reply_doserror(req, ERRDOS, error);
6854 reply_outbuf(req, 1, 0);
6855 SSVAL(req->outbuf,smb_vwv0,count);
6857 TALLOC_FREE(smb_fname);
6858 TALLOC_FREE(smb_fname_new);
6859 END_PROFILE(SMBcopy);
6864 #define DBGC_CLASS DBGC_LOCKING
6866 /****************************************************************************
6867 Get a lock pid, dealing with large count requests.
6868 ****************************************************************************/
6870 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6871 bool large_file_format)
6873 if(!large_file_format)
6874 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6876 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6879 /****************************************************************************
6880 Get a lock count, dealing with large count requests.
6881 ****************************************************************************/
6883 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6884 bool large_file_format)
6888 if(!large_file_format) {
6889 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6892 #if defined(HAVE_LONGLONG)
6893 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6894 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6895 #else /* HAVE_LONGLONG */
6898 * NT4.x seems to be broken in that it sends large file (64 bit)
6899 * lockingX calls even if the CAP_LARGE_FILES was *not*
6900 * negotiated. For boxes without large unsigned ints truncate the
6901 * lock count by dropping the top 32 bits.
6904 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6905 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6906 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6907 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6908 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6911 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6912 #endif /* HAVE_LONGLONG */
6918 #if !defined(HAVE_LONGLONG)
6919 /****************************************************************************
6920 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6921 ****************************************************************************/
6923 static uint32 map_lock_offset(uint32 high, uint32 low)
6927 uint32 highcopy = high;
6930 * Try and find out how many significant bits there are in high.
6933 for(i = 0; highcopy; i++)
6937 * We use 31 bits not 32 here as POSIX
6938 * lock offsets may not be negative.
6941 mask = (~0) << (31 - i);
6944 return 0; /* Fail. */
6950 #endif /* !defined(HAVE_LONGLONG) */
6952 /****************************************************************************
6953 Get a lock offset, dealing with large offset requests.
6954 ****************************************************************************/
6956 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6957 bool large_file_format, bool *err)
6959 uint64_t offset = 0;
6963 if(!large_file_format) {
6964 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6967 #if defined(HAVE_LONGLONG)
6968 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6969 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6970 #else /* HAVE_LONGLONG */
6973 * NT4.x seems to be broken in that it sends large file (64 bit)
6974 * lockingX calls even if the CAP_LARGE_FILES was *not*
6975 * negotiated. For boxes without large unsigned ints mangle the
6976 * lock offset by mapping the top 32 bits onto the lower 32.
6979 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6980 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6981 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6984 if((new_low = map_lock_offset(high, low)) == 0) {
6986 return (uint64_t)-1;
6989 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6990 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6991 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6992 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6995 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6996 #endif /* HAVE_LONGLONG */
7002 /****************************************************************************
7003 Reply to a lockingX request.
7004 ****************************************************************************/
7006 void reply_lockingX(struct smb_request *req)
7008 connection_struct *conn = req->conn;
7010 unsigned char locktype;
7011 unsigned char oplocklevel;
7014 uint64_t count = 0, offset = 0;
7018 const uint8_t *data;
7019 bool large_file_format;
7021 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7023 START_PROFILE(SMBlockingX);
7026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7027 END_PROFILE(SMBlockingX);
7031 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7032 locktype = CVAL(req->vwv+3, 0);
7033 oplocklevel = CVAL(req->vwv+3, 1);
7034 num_ulocks = SVAL(req->vwv+6, 0);
7035 num_locks = SVAL(req->vwv+7, 0);
7036 lock_timeout = IVAL(req->vwv+4, 0);
7037 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7039 if (!check_fsp(conn, req, fsp)) {
7040 END_PROFILE(SMBlockingX);
7046 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7047 /* we don't support these - and CANCEL_LOCK makes w2k
7048 and XP reboot so I don't really want to be
7049 compatible! (tridge) */
7050 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7051 END_PROFILE(SMBlockingX);
7055 /* Check if this is an oplock break on a file
7056 we have granted an oplock on.
7058 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7059 /* Client can insist on breaking to none. */
7060 bool break_to_none = (oplocklevel == 0);
7063 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7064 "for fnum = %d\n", (unsigned int)oplocklevel,
7068 * Make sure we have granted an exclusive or batch oplock on
7072 if (fsp->oplock_type == 0) {
7074 /* The Samba4 nbench simulator doesn't understand
7075 the difference between break to level2 and break
7076 to none from level2 - it sends oplock break
7077 replies in both cases. Don't keep logging an error
7078 message here - just ignore it. JRA. */
7080 DEBUG(5,("reply_lockingX: Error : oplock break from "
7081 "client for fnum = %d (oplock=%d) and no "
7082 "oplock granted on this file (%s).\n",
7083 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
7085 /* if this is a pure oplock break request then don't
7087 if (num_locks == 0 && num_ulocks == 0) {
7088 END_PROFILE(SMBlockingX);
7091 END_PROFILE(SMBlockingX);
7092 reply_doserror(req, ERRDOS, ERRlock);
7097 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7099 result = remove_oplock(fsp);
7101 result = downgrade_oplock(fsp);
7105 DEBUG(0, ("reply_lockingX: error in removing "
7106 "oplock on file %s\n", fsp->fsp_name));
7107 /* Hmmm. Is this panic justified? */
7108 smb_panic("internal tdb error");
7111 reply_to_oplock_break_requests(fsp);
7113 /* if this is a pure oplock break request then don't send a
7115 if (num_locks == 0 && num_ulocks == 0) {
7116 /* Sanity check - ensure a pure oplock break is not a
7118 if(CVAL(req->vwv+0, 0) != 0xff)
7119 DEBUG(0,("reply_lockingX: Error : pure oplock "
7120 "break is a chained %d request !\n",
7121 (unsigned int)CVAL(req->vwv+0, 0)));
7122 END_PROFILE(SMBlockingX);
7128 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7129 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7130 END_PROFILE(SMBlockingX);
7134 /* Data now points at the beginning of the list
7135 of smb_unlkrng structs */
7136 for(i = 0; i < (int)num_ulocks; i++) {
7137 lock_pid = get_lock_pid( data, i, large_file_format);
7138 count = get_lock_count( data, i, large_file_format);
7139 offset = get_lock_offset( data, i, large_file_format, &err);
7142 * There is no error code marked "stupid client bug".... :-).
7145 END_PROFILE(SMBlockingX);
7146 reply_doserror(req, ERRDOS, ERRnoaccess);
7150 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
7151 "pid %u, file %s\n", (double)offset, (double)count,
7152 (unsigned int)lock_pid, fsp->fsp_name ));
7154 status = do_unlock(smbd_messaging_context(),
7161 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
7162 nt_errstr(status)));
7164 if (NT_STATUS_V(status)) {
7165 END_PROFILE(SMBlockingX);
7166 reply_nterror(req, status);
7171 /* Setup the timeout in seconds. */
7173 if (!lp_blocking_locks(SNUM(conn))) {
7177 /* Now do any requested locks */
7178 data += ((large_file_format ? 20 : 10)*num_ulocks);
7180 /* Data now points at the beginning of the list
7181 of smb_lkrng structs */
7183 for(i = 0; i < (int)num_locks; i++) {
7184 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
7185 READ_LOCK:WRITE_LOCK);
7186 lock_pid = get_lock_pid( data, i, large_file_format);
7187 count = get_lock_count( data, i, large_file_format);
7188 offset = get_lock_offset( data, i, large_file_format, &err);
7191 * There is no error code marked "stupid client bug".... :-).
7194 END_PROFILE(SMBlockingX);
7195 reply_doserror(req, ERRDOS, ERRnoaccess);
7199 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
7200 "%u, file %s timeout = %d\n", (double)offset,
7201 (double)count, (unsigned int)lock_pid,
7202 fsp->fsp_name, (int)lock_timeout ));
7204 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7205 struct blocking_lock_record *blr = NULL;
7207 if (lp_blocking_locks(SNUM(conn))) {
7209 /* Schedule a message to ourselves to
7210 remove the blocking lock record and
7211 return the right error. */
7213 blr = blocking_lock_cancel(fsp,
7219 NT_STATUS_FILE_LOCK_CONFLICT);
7221 END_PROFILE(SMBlockingX);
7226 ERRcancelviolation));
7230 /* Remove a matching pending lock. */
7231 status = do_lock_cancel(fsp,
7238 bool blocking_lock = lock_timeout ? True : False;
7239 bool defer_lock = False;
7240 struct byte_range_lock *br_lck;
7241 uint32 block_smbpid;
7243 br_lck = do_lock(smbd_messaging_context(),
7255 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7256 /* Windows internal resolution for blocking locks seems
7257 to be about 200ms... Don't wait for less than that. JRA. */
7258 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7259 lock_timeout = lp_lock_spin_time();
7264 /* This heuristic seems to match W2K3 very well. If a
7265 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7266 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7267 far as I can tell. Replacement for do_lock_spin(). JRA. */
7269 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7270 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7272 lock_timeout = lp_lock_spin_time();
7275 if (br_lck && defer_lock) {
7277 * A blocking lock was requested. Package up
7278 * this smb into a queued request and push it
7279 * onto the blocking lock queue.
7281 if(push_blocking_lock_request(br_lck,
7292 TALLOC_FREE(br_lck);
7293 END_PROFILE(SMBlockingX);
7298 TALLOC_FREE(br_lck);
7301 if (NT_STATUS_V(status)) {
7302 END_PROFILE(SMBlockingX);
7303 reply_nterror(req, status);
7308 /* If any of the above locks failed, then we must unlock
7309 all of the previous locks (X/Open spec). */
7311 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7315 * Ensure we don't do a remove on the lock that just failed,
7316 * as under POSIX rules, if we have a lock already there, we
7317 * will delete it (and we shouldn't) .....
7319 for(i--; i >= 0; i--) {
7320 lock_pid = get_lock_pid( data, i, large_file_format);
7321 count = get_lock_count( data, i, large_file_format);
7322 offset = get_lock_offset( data, i, large_file_format,
7326 * There is no error code marked "stupid client
7330 END_PROFILE(SMBlockingX);
7331 reply_doserror(req, ERRDOS, ERRnoaccess);
7335 do_unlock(smbd_messaging_context(),
7342 END_PROFILE(SMBlockingX);
7343 reply_nterror(req, status);
7347 reply_outbuf(req, 2, 0);
7349 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7350 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7352 END_PROFILE(SMBlockingX);
7357 #define DBGC_CLASS DBGC_ALL
7359 /****************************************************************************
7360 Reply to a SMBreadbmpx (read block multiplex) request.
7361 Always reply with an error, if someone has a platform really needs this,
7362 please contact vl@samba.org
7363 ****************************************************************************/
7365 void reply_readbmpx(struct smb_request *req)
7367 START_PROFILE(SMBreadBmpx);
7368 reply_doserror(req, ERRSRV, ERRuseSTD);
7369 END_PROFILE(SMBreadBmpx);
7373 /****************************************************************************
7374 Reply to a SMBreadbs (read block multiplex secondary) request.
7375 Always reply with an error, if someone has a platform really needs this,
7376 please contact vl@samba.org
7377 ****************************************************************************/
7379 void reply_readbs(struct smb_request *req)
7381 START_PROFILE(SMBreadBs);
7382 reply_doserror(req, ERRSRV, ERRuseSTD);
7383 END_PROFILE(SMBreadBs);
7387 /****************************************************************************
7388 Reply to a SMBsetattrE.
7389 ****************************************************************************/
7391 void reply_setattrE(struct smb_request *req)
7393 connection_struct *conn = req->conn;
7394 struct smb_file_time ft;
7396 SMB_STRUCT_STAT sbuf;
7399 START_PROFILE(SMBsetattrE);
7403 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7404 END_PROFILE(SMBsetattrE);
7408 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7410 if(!fsp || (fsp->conn != conn)) {
7411 reply_doserror(req, ERRDOS, ERRbadfid);
7412 END_PROFILE(SMBsetattrE);
7418 * Convert the DOS times into unix times.
7421 ft.atime = convert_time_t_to_timespec(
7422 srv_make_unix_date2(req->vwv+3));
7423 ft.mtime = convert_time_t_to_timespec(
7424 srv_make_unix_date2(req->vwv+5));
7425 ft.create_time = convert_time_t_to_timespec(
7426 srv_make_unix_date2(req->vwv+1));
7428 reply_outbuf(req, 0, 0);
7431 * Patch from Ray Frush <frush@engr.colostate.edu>
7432 * Sometimes times are sent as zero - ignore them.
7435 /* Ensure we have a valid stat struct for the source. */
7436 if (fsp->fh->fd != -1) {
7437 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7438 status = map_nt_error_from_unix(errno);
7439 reply_nterror(req, status);
7440 END_PROFILE(SMBsetattrE);
7446 if (fsp->posix_open) {
7447 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
7449 ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
7452 status = map_nt_error_from_unix(errno);
7453 reply_nterror(req, status);
7454 END_PROFILE(SMBsetattrE);
7459 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7461 if (!NT_STATUS_IS_OK(status)) {
7462 reply_doserror(req, ERRDOS, ERRnoaccess);
7463 END_PROFILE(SMBsetattrE);
7467 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7470 (unsigned int)ft.atime.tv_sec,
7471 (unsigned int)ft.mtime.tv_sec,
7472 (unsigned int)ft.create_time.tv_sec
7475 END_PROFILE(SMBsetattrE);
7480 /* Back from the dead for OS/2..... JRA. */
7482 /****************************************************************************
7483 Reply to a SMBwritebmpx (write block multiplex primary) request.
7484 Always reply with an error, if someone has a platform really needs this,
7485 please contact vl@samba.org
7486 ****************************************************************************/
7488 void reply_writebmpx(struct smb_request *req)
7490 START_PROFILE(SMBwriteBmpx);
7491 reply_doserror(req, ERRSRV, ERRuseSTD);
7492 END_PROFILE(SMBwriteBmpx);
7496 /****************************************************************************
7497 Reply to a SMBwritebs (write block multiplex secondary) request.
7498 Always reply with an error, if someone has a platform really needs this,
7499 please contact vl@samba.org
7500 ****************************************************************************/
7502 void reply_writebs(struct smb_request *req)
7504 START_PROFILE(SMBwriteBs);
7505 reply_doserror(req, ERRSRV, ERRuseSTD);
7506 END_PROFILE(SMBwriteBs);
7510 /****************************************************************************
7511 Reply to a SMBgetattrE.
7512 ****************************************************************************/
7514 void reply_getattrE(struct smb_request *req)
7516 connection_struct *conn = req->conn;
7517 SMB_STRUCT_STAT sbuf;
7520 struct timespec create_ts;
7522 START_PROFILE(SMBgetattrE);
7525 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7526 END_PROFILE(SMBgetattrE);
7530 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7532 if(!fsp || (fsp->conn != conn)) {
7533 reply_doserror(req, ERRDOS, ERRbadfid);
7534 END_PROFILE(SMBgetattrE);
7538 /* Do an fstat on this file */
7539 if(fsp_stat(fsp, &sbuf)) {
7540 reply_unixerror(req, ERRDOS, ERRnoaccess);
7541 END_PROFILE(SMBgetattrE);
7545 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7548 * Convert the times into dos times. Set create
7549 * date to be last modify date as UNIX doesn't save
7553 reply_outbuf(req, 11, 0);
7555 create_ts = sbuf.st_ex_btime;
7556 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7557 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7558 convert_timespec_to_time_t(sbuf.st_ex_atime));
7559 /* Should we check pending modtime here ? JRA */
7560 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7561 convert_timespec_to_time_t(sbuf.st_ex_mtime));
7564 SIVAL(req->outbuf, smb_vwv6, 0);
7565 SIVAL(req->outbuf, smb_vwv8, 0);
7567 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7568 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_ex_size);
7569 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7571 SSVAL(req->outbuf,smb_vwv10, mode);
7573 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7575 END_PROFILE(SMBgetattrE);