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 *)&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;
689 START_PROFILE(SMBtconX);
692 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
693 END_PROFILE(SMBtconX);
697 passlen = SVAL(req->vwv+3, 0);
698 tcon_flags = SVAL(req->vwv+2, 0);
700 /* we might have to close an old one */
701 if ((tcon_flags & 0x1) && conn) {
702 close_cnum(conn,req->vuid);
707 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
708 reply_doserror(req, ERRDOS, ERRbuftoosmall);
709 END_PROFILE(SMBtconX);
713 if (global_encrypted_passwords_negotiated) {
714 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
715 if (lp_security() == SEC_SHARE) {
717 * Security = share always has a pad byte
718 * after the password.
720 p = (const char *)req->buf + passlen + 1;
722 p = (const char *)req->buf + passlen;
725 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
726 /* Ensure correct termination */
727 password.data[passlen]=0;
728 p = (const char *)req->buf + passlen + 1;
731 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
734 data_blob_clear_free(&password);
735 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
736 END_PROFILE(SMBtconX);
741 * the service name can be either: \\server\share
742 * or share directly like on the DELL PowerVault 705
745 q = strchr_m(path+2,'\\');
747 data_blob_clear_free(&password);
748 reply_doserror(req, ERRDOS, ERRnosuchshare);
749 END_PROFILE(SMBtconX);
757 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
758 &client_devicetype, p,
759 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
761 if (client_devicetype == NULL) {
762 data_blob_clear_free(&password);
763 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
764 END_PROFILE(SMBtconX);
768 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
770 conn = make_connection(service, password, client_devicetype,
771 req->vuid, &nt_status);
774 data_blob_clear_free(&password);
777 reply_nterror(req, nt_status);
778 END_PROFILE(SMBtconX);
783 server_devicetype = "IPC";
784 else if ( IS_PRINT(conn) )
785 server_devicetype = "LPT1:";
787 server_devicetype = "A:";
789 if (Protocol < PROTOCOL_NT1) {
790 reply_outbuf(req, 2, 0);
791 if (message_push_string(&req->outbuf, server_devicetype,
792 STR_TERMINATE|STR_ASCII) == -1) {
793 reply_nterror(req, NT_STATUS_NO_MEMORY);
794 END_PROFILE(SMBtconX);
798 /* NT sets the fstype of IPC$ to the null string */
799 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
801 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
802 /* Return permissions. */
806 reply_outbuf(req, 7, 0);
809 perm1 = FILE_ALL_ACCESS;
810 perm2 = FILE_ALL_ACCESS;
812 perm1 = CAN_WRITE(conn) ?
817 SIVAL(req->outbuf, smb_vwv3, perm1);
818 SIVAL(req->outbuf, smb_vwv5, perm2);
820 reply_outbuf(req, 3, 0);
823 if ((message_push_string(&req->outbuf, server_devicetype,
824 STR_TERMINATE|STR_ASCII) == -1)
825 || (message_push_string(&req->outbuf, fstype,
826 STR_TERMINATE) == -1)) {
827 reply_nterror(req, NT_STATUS_NO_MEMORY);
828 END_PROFILE(SMBtconX);
832 /* what does setting this bit do? It is set by NT4 and
833 may affect the ability to autorun mounted cdroms */
834 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
835 (lp_csc_policy(SNUM(conn)) << 2));
837 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
838 DEBUG(2,("Serving %s as a Dfs root\n",
839 lp_servicename(SNUM(conn)) ));
840 SSVAL(req->outbuf, smb_vwv2,
841 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
846 DEBUG(3,("tconX service=%s \n",
849 /* set the incoming and outgoing tid to the just created one */
850 SSVAL(req->inbuf,smb_tid,conn->cnum);
851 SSVAL(req->outbuf,smb_tid,conn->cnum);
853 END_PROFILE(SMBtconX);
859 /****************************************************************************
860 Reply to an unknown type.
861 ****************************************************************************/
863 void reply_unknown_new(struct smb_request *req, uint8 type)
865 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
866 smb_fn_name(type), type, type));
867 reply_doserror(req, ERRSRV, ERRunknownsmb);
871 /****************************************************************************
873 conn POINTER CAN BE NULL HERE !
874 ****************************************************************************/
876 void reply_ioctl(struct smb_request *req)
878 connection_struct *conn = req->conn;
885 START_PROFILE(SMBioctl);
888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
889 END_PROFILE(SMBioctl);
893 device = SVAL(req->vwv+1, 0);
894 function = SVAL(req->vwv+2, 0);
895 ioctl_code = (device << 16) + function;
897 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
899 switch (ioctl_code) {
900 case IOCTL_QUERY_JOB_INFO:
904 reply_doserror(req, ERRSRV, ERRnosupport);
905 END_PROFILE(SMBioctl);
909 reply_outbuf(req, 8, replysize+1);
910 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
911 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
912 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
913 p = smb_buf(req->outbuf);
914 memset(p, '\0', replysize+1); /* valgrind-safe. */
915 p += 1; /* Allow for alignment */
917 switch (ioctl_code) {
918 case IOCTL_QUERY_JOB_INFO:
920 files_struct *fsp = file_fsp(
921 req, SVAL(req->vwv+0, 0));
923 reply_doserror(req, ERRDOS, ERRbadfid);
924 END_PROFILE(SMBioctl);
927 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
928 srvstr_push((char *)req->outbuf, req->flags2, p+2,
930 STR_TERMINATE|STR_ASCII);
932 srvstr_push((char *)req->outbuf, req->flags2,
933 p+18, lp_servicename(SNUM(conn)),
934 13, STR_TERMINATE|STR_ASCII);
942 END_PROFILE(SMBioctl);
946 /****************************************************************************
947 Strange checkpath NTSTATUS mapping.
948 ****************************************************************************/
950 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
952 /* Strange DOS error code semantics only for checkpath... */
953 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
954 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
955 /* We need to map to ERRbadpath */
956 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
962 /****************************************************************************
963 Reply to a checkpath.
964 ****************************************************************************/
966 void reply_checkpath(struct smb_request *req)
968 connection_struct *conn = req->conn;
970 SMB_STRUCT_STAT sbuf;
972 TALLOC_CTX *ctx = talloc_tos();
974 START_PROFILE(SMBcheckpath);
976 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
977 STR_TERMINATE, &status);
979 if (!NT_STATUS_IS_OK(status)) {
980 status = map_checkpath_error(req->flags2, status);
981 reply_nterror(req, status);
982 END_PROFILE(SMBcheckpath);
986 status = resolve_dfspath(ctx, conn,
987 req->flags2 & FLAGS2_DFS_PATHNAMES,
990 if (!NT_STATUS_IS_OK(status)) {
991 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
992 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
994 END_PROFILE(SMBcheckpath);
1000 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1002 status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf);
1003 if (!NT_STATUS_IS_OK(status)) {
1007 status = check_name(conn, name);
1008 if (!NT_STATUS_IS_OK(status)) {
1009 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
1013 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
1014 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
1015 status = map_nt_error_from_unix(errno);
1019 if (!S_ISDIR(sbuf.st_mode)) {
1020 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1021 ERRDOS, ERRbadpath);
1022 END_PROFILE(SMBcheckpath);
1026 reply_outbuf(req, 0, 0);
1028 END_PROFILE(SMBcheckpath);
1033 END_PROFILE(SMBcheckpath);
1035 /* We special case this - as when a Windows machine
1036 is parsing a path is steps through the components
1037 one at a time - if a component fails it expects
1038 ERRbadpath, not ERRbadfile.
1040 status = map_checkpath_error(req->flags2, status);
1041 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1043 * Windows returns different error codes if
1044 * the parent directory is valid but not the
1045 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1046 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1047 * if the path is invalid.
1049 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1050 ERRDOS, ERRbadpath);
1054 reply_nterror(req, status);
1057 /****************************************************************************
1059 ****************************************************************************/
1061 void reply_getatr(struct smb_request *req)
1063 connection_struct *conn = req->conn;
1065 SMB_STRUCT_STAT sbuf;
1071 TALLOC_CTX *ctx = talloc_tos();
1073 START_PROFILE(SMBgetatr);
1075 p = (const char *)req->buf + 1;
1076 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1077 if (!NT_STATUS_IS_OK(status)) {
1078 reply_nterror(req, status);
1079 END_PROFILE(SMBgetatr);
1083 status = resolve_dfspath(ctx, conn,
1084 req->flags2 & FLAGS2_DFS_PATHNAMES,
1087 if (!NT_STATUS_IS_OK(status)) {
1088 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1089 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1090 ERRSRV, ERRbadpath);
1091 END_PROFILE(SMBgetatr);
1094 reply_nterror(req, status);
1095 END_PROFILE(SMBgetatr);
1099 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1100 under WfWg - weird! */
1101 if (*fname == '\0') {
1102 mode = aHIDDEN | aDIR;
1103 if (!CAN_WRITE(conn)) {
1109 status = unix_convert(ctx, conn, fname, False, &fname, NULL,&sbuf);
1110 if (!NT_STATUS_IS_OK(status)) {
1111 reply_nterror(req, status);
1112 END_PROFILE(SMBgetatr);
1115 status = check_name(conn, fname);
1116 if (!NT_STATUS_IS_OK(status)) {
1117 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1118 reply_nterror(req, status);
1119 END_PROFILE(SMBgetatr);
1122 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
1123 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1124 reply_unixerror(req, ERRDOS,ERRbadfile);
1125 END_PROFILE(SMBgetatr);
1129 mode = dos_mode(conn,fname,&sbuf);
1130 size = sbuf.st_size;
1131 mtime = sbuf.st_mtime;
1137 reply_outbuf(req, 10, 0);
1139 SSVAL(req->outbuf,smb_vwv0,mode);
1140 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1141 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1143 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1145 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1147 if (Protocol >= PROTOCOL_NT1) {
1148 SSVAL(req->outbuf, smb_flg2,
1149 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1152 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1154 END_PROFILE(SMBgetatr);
1158 /****************************************************************************
1160 ****************************************************************************/
1162 void reply_setatr(struct smb_request *req)
1164 struct smb_file_time ft;
1165 connection_struct *conn = req->conn;
1169 SMB_STRUCT_STAT sbuf;
1172 TALLOC_CTX *ctx = talloc_tos();
1174 START_PROFILE(SMBsetatr);
1179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1183 p = (const char *)req->buf + 1;
1184 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1185 if (!NT_STATUS_IS_OK(status)) {
1186 reply_nterror(req, status);
1187 END_PROFILE(SMBsetatr);
1191 status = resolve_dfspath(ctx, conn,
1192 req->flags2 & FLAGS2_DFS_PATHNAMES,
1195 if (!NT_STATUS_IS_OK(status)) {
1196 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1197 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1198 ERRSRV, ERRbadpath);
1199 END_PROFILE(SMBsetatr);
1202 reply_nterror(req, status);
1203 END_PROFILE(SMBsetatr);
1207 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
1208 if (!NT_STATUS_IS_OK(status)) {
1209 reply_nterror(req, status);
1210 END_PROFILE(SMBsetatr);
1214 status = check_name(conn, fname);
1215 if (!NT_STATUS_IS_OK(status)) {
1216 reply_nterror(req, status);
1217 END_PROFILE(SMBsetatr);
1221 if (fname[0] == '.' && fname[1] == '\0') {
1223 * Not sure here is the right place to catch this
1224 * condition. Might be moved to somewhere else later -- vl
1226 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1227 END_PROFILE(SMBsetatr);
1231 mode = SVAL(req->vwv+0, 0);
1232 mtime = srv_make_unix_date3(req->vwv+1);
1234 ft.mtime = convert_time_t_to_timespec(mtime);
1235 status = smb_set_file_time(conn, NULL, fname,
1237 if (!NT_STATUS_IS_OK(status)) {
1238 reply_unixerror(req, ERRDOS, ERRnoaccess);
1239 END_PROFILE(SMBsetatr);
1243 if (mode != FILE_ATTRIBUTE_NORMAL) {
1244 if (VALID_STAT_OF_DIR(sbuf))
1249 if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) {
1250 reply_unixerror(req, ERRDOS, ERRnoaccess);
1251 END_PROFILE(SMBsetatr);
1256 reply_outbuf(req, 0, 0);
1258 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1260 END_PROFILE(SMBsetatr);
1264 /****************************************************************************
1266 ****************************************************************************/
1268 void reply_dskattr(struct smb_request *req)
1270 connection_struct *conn = req->conn;
1271 uint64_t dfree,dsize,bsize;
1272 START_PROFILE(SMBdskattr);
1274 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1275 reply_unixerror(req, ERRHRD, ERRgeneral);
1276 END_PROFILE(SMBdskattr);
1280 reply_outbuf(req, 5, 0);
1282 if (Protocol <= PROTOCOL_LANMAN2) {
1283 double total_space, free_space;
1284 /* we need to scale this to a number that DOS6 can handle. We
1285 use floating point so we can handle large drives on systems
1286 that don't have 64 bit integers
1288 we end up displaying a maximum of 2G to DOS systems
1290 total_space = dsize * (double)bsize;
1291 free_space = dfree * (double)bsize;
1293 dsize = (uint64_t)((total_space+63*512) / (64*512));
1294 dfree = (uint64_t)((free_space+63*512) / (64*512));
1296 if (dsize > 0xFFFF) dsize = 0xFFFF;
1297 if (dfree > 0xFFFF) dfree = 0xFFFF;
1299 SSVAL(req->outbuf,smb_vwv0,dsize);
1300 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1301 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1302 SSVAL(req->outbuf,smb_vwv3,dfree);
1304 SSVAL(req->outbuf,smb_vwv0,dsize);
1305 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1306 SSVAL(req->outbuf,smb_vwv2,512);
1307 SSVAL(req->outbuf,smb_vwv3,dfree);
1310 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1312 END_PROFILE(SMBdskattr);
1316 /****************************************************************************
1318 Can be called from SMBsearch, SMBffirst or SMBfunique.
1319 ****************************************************************************/
1321 void reply_search(struct smb_request *req)
1323 connection_struct *conn = req->conn;
1324 const char *mask = NULL;
1325 char *directory = NULL;
1331 unsigned int numentries = 0;
1332 unsigned int maxentries = 0;
1333 bool finished = False;
1339 bool check_descend = False;
1340 bool expect_close = False;
1342 bool mask_contains_wcard = False;
1343 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1344 TALLOC_CTX *ctx = talloc_tos();
1345 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1347 START_PROFILE(SMBsearch);
1350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1351 END_PROFILE(SMBsearch);
1355 if (lp_posix_pathnames()) {
1356 reply_unknown_new(req, req->cmd);
1357 END_PROFILE(SMBsearch);
1361 /* If we were called as SMBffirst then we must expect close. */
1362 if(req->cmd == SMBffirst) {
1363 expect_close = True;
1366 reply_outbuf(req, 1, 3);
1367 maxentries = SVAL(req->vwv+0, 0);
1368 dirtype = SVAL(req->vwv+1, 0);
1369 p = (const char *)req->buf + 1;
1370 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1371 &nt_status, &mask_contains_wcard);
1372 if (!NT_STATUS_IS_OK(nt_status)) {
1373 reply_nterror(req, nt_status);
1374 END_PROFILE(SMBsearch);
1378 nt_status = resolve_dfspath_wcard(ctx, conn,
1379 req->flags2 & FLAGS2_DFS_PATHNAMES,
1382 &mask_contains_wcard);
1383 if (!NT_STATUS_IS_OK(nt_status)) {
1384 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1385 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1386 ERRSRV, ERRbadpath);
1387 END_PROFILE(SMBsearch);
1390 reply_nterror(req, nt_status);
1391 END_PROFILE(SMBsearch);
1396 status_len = SVAL(p, 0);
1399 /* dirtype &= ~aDIR; */
1401 if (status_len == 0) {
1402 SMB_STRUCT_STAT sbuf;
1404 nt_status = unix_convert(ctx, conn, path, True,
1405 &directory, NULL, &sbuf);
1406 if (!NT_STATUS_IS_OK(nt_status)) {
1407 reply_nterror(req, nt_status);
1408 END_PROFILE(SMBsearch);
1412 nt_status = check_name(conn, directory);
1413 if (!NT_STATUS_IS_OK(nt_status)) {
1414 reply_nterror(req, nt_status);
1415 END_PROFILE(SMBsearch);
1419 p = strrchr_m(directory,'/');
1420 if ((p != NULL) && (*directory != '/')) {
1422 directory = talloc_strndup(ctx, directory,
1423 PTR_DIFF(p, directory));
1426 directory = talloc_strdup(ctx,".");
1430 reply_nterror(req, NT_STATUS_NO_MEMORY);
1431 END_PROFILE(SMBsearch);
1435 memset((char *)status,'\0',21);
1436 SCVAL(status,0,(dirtype & 0x1F));
1438 nt_status = dptr_create(conn,
1444 mask_contains_wcard,
1447 if (!NT_STATUS_IS_OK(nt_status)) {
1448 reply_nterror(req, nt_status);
1449 END_PROFILE(SMBsearch);
1452 dptr_num = dptr_dnum(conn->dirptr);
1456 memcpy(status,p,21);
1457 status_dirtype = CVAL(status,0) & 0x1F;
1458 if (status_dirtype != (dirtype & 0x1F)) {
1459 dirtype = status_dirtype;
1462 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1463 if (!conn->dirptr) {
1466 string_set(&conn->dirpath,dptr_path(dptr_num));
1467 mask = dptr_wcard(dptr_num);
1472 * For a 'continue' search we have no string. So
1473 * check from the initial saved string.
1475 mask_contains_wcard = ms_has_wild(mask);
1476 dirtype = dptr_attr(dptr_num);
1479 DEBUG(4,("dptr_num is %d\n",dptr_num));
1481 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1482 dptr_init_search_op(conn->dirptr);
1484 if ((dirtype&0x1F) == aVOLID) {
1485 char buf[DIR_STRUCT_SIZE];
1486 memcpy(buf,status,21);
1487 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1488 0,aVOLID,0,!allow_long_path_components)) {
1489 reply_nterror(req, NT_STATUS_NO_MEMORY);
1490 END_PROFILE(SMBsearch);
1493 dptr_fill(buf+12,dptr_num);
1494 if (dptr_zero(buf+12) && (status_len==0)) {
1499 if (message_push_blob(&req->outbuf,
1500 data_blob_const(buf, sizeof(buf)))
1502 reply_nterror(req, NT_STATUS_NO_MEMORY);
1503 END_PROFILE(SMBsearch);
1511 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1514 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1515 conn->dirpath,lp_dontdescend(SNUM(conn))));
1516 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1517 check_descend = True;
1520 for (i=numentries;(i<maxentries) && !finished;i++) {
1521 finished = !get_dir_entry(ctx,
1532 char buf[DIR_STRUCT_SIZE];
1533 memcpy(buf,status,21);
1534 if (!make_dir_struct(ctx,
1541 !allow_long_path_components)) {
1542 reply_nterror(req, NT_STATUS_NO_MEMORY);
1543 END_PROFILE(SMBsearch);
1546 if (!dptr_fill(buf+12,dptr_num)) {
1549 if (message_push_blob(&req->outbuf,
1550 data_blob_const(buf, sizeof(buf)))
1552 reply_nterror(req, NT_STATUS_NO_MEMORY);
1553 END_PROFILE(SMBsearch);
1563 /* If we were called as SMBffirst with smb_search_id == NULL
1564 and no entries were found then return error and close dirptr
1567 if (numentries == 0) {
1568 dptr_close(&dptr_num);
1569 } else if(expect_close && status_len == 0) {
1570 /* Close the dptr - we know it's gone */
1571 dptr_close(&dptr_num);
1574 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1575 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1576 dptr_close(&dptr_num);
1579 if ((numentries == 0) && !mask_contains_wcard) {
1580 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1581 END_PROFILE(SMBsearch);
1585 SSVAL(req->outbuf,smb_vwv0,numentries);
1586 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1587 SCVAL(smb_buf(req->outbuf),0,5);
1588 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1590 /* The replies here are never long name. */
1591 SSVAL(req->outbuf, smb_flg2,
1592 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1593 if (!allow_long_path_components) {
1594 SSVAL(req->outbuf, smb_flg2,
1595 SVAL(req->outbuf, smb_flg2)
1596 & (~FLAGS2_LONG_PATH_COMPONENTS));
1599 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1600 SSVAL(req->outbuf, smb_flg2,
1601 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1604 directory = dptr_path(dptr_num);
1607 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1608 smb_fn_name(req->cmd),
1610 directory ? directory : "./",
1615 END_PROFILE(SMBsearch);
1619 /****************************************************************************
1620 Reply to a fclose (stop directory search).
1621 ****************************************************************************/
1623 void reply_fclose(struct smb_request *req)
1631 bool path_contains_wcard = False;
1632 TALLOC_CTX *ctx = talloc_tos();
1634 START_PROFILE(SMBfclose);
1636 if (lp_posix_pathnames()) {
1637 reply_unknown_new(req, req->cmd);
1638 END_PROFILE(SMBfclose);
1642 p = (const char *)req->buf + 1;
1643 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1644 &err, &path_contains_wcard);
1645 if (!NT_STATUS_IS_OK(err)) {
1646 reply_nterror(req, err);
1647 END_PROFILE(SMBfclose);
1651 status_len = SVAL(p,0);
1654 if (status_len == 0) {
1655 reply_doserror(req, ERRSRV, ERRsrverror);
1656 END_PROFILE(SMBfclose);
1660 memcpy(status,p,21);
1662 if(dptr_fetch(status+12,&dptr_num)) {
1663 /* Close the dptr - we know it's gone */
1664 dptr_close(&dptr_num);
1667 reply_outbuf(req, 1, 0);
1668 SSVAL(req->outbuf,smb_vwv0,0);
1670 DEBUG(3,("search close\n"));
1672 END_PROFILE(SMBfclose);
1676 /****************************************************************************
1678 ****************************************************************************/
1680 void reply_open(struct smb_request *req)
1682 connection_struct *conn = req->conn;
1688 SMB_STRUCT_STAT sbuf;
1695 uint32 create_disposition;
1696 uint32 create_options = 0;
1698 TALLOC_CTX *ctx = talloc_tos();
1700 START_PROFILE(SMBopen);
1702 SET_STAT_INVALID(sbuf);
1705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1706 END_PROFILE(SMBopen);
1710 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1711 deny_mode = SVAL(req->vwv+0, 0);
1712 dos_attr = SVAL(req->vwv+1, 0);
1714 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1715 STR_TERMINATE, &status);
1716 if (!NT_STATUS_IS_OK(status)) {
1717 reply_nterror(req, status);
1718 END_PROFILE(SMBopen);
1722 if (!map_open_params_to_ntcreate(
1723 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1724 &share_mode, &create_disposition, &create_options)) {
1725 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1726 END_PROFILE(SMBopen);
1730 status = SMB_VFS_CREATE_FILE(
1733 0, /* root_dir_fid */
1735 CFF_DOS_PATH, /* create_file_flags */
1736 access_mask, /* access_mask */
1737 share_mode, /* share_access */
1738 create_disposition, /* create_disposition*/
1739 create_options, /* create_options */
1740 dos_attr, /* file_attributes */
1741 oplock_request, /* oplock_request */
1742 0, /* allocation_size */
1749 if (!NT_STATUS_IS_OK(status)) {
1750 if (open_was_deferred(req->mid)) {
1751 /* We have re-scheduled this call. */
1752 END_PROFILE(SMBopen);
1755 reply_openerror(req, status);
1756 END_PROFILE(SMBopen);
1760 size = sbuf.st_size;
1761 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1762 mtime = sbuf.st_mtime;
1765 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1766 close_file(req, fsp, ERROR_CLOSE);
1767 reply_doserror(req, ERRDOS,ERRnoaccess);
1768 END_PROFILE(SMBopen);
1772 reply_outbuf(req, 7, 0);
1773 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1774 SSVAL(req->outbuf,smb_vwv1,fattr);
1775 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1776 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1778 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1780 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1781 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1783 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1784 SCVAL(req->outbuf,smb_flg,
1785 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1788 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1789 SCVAL(req->outbuf,smb_flg,
1790 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1792 END_PROFILE(SMBopen);
1796 /****************************************************************************
1797 Reply to an open and X.
1798 ****************************************************************************/
1800 void reply_open_and_X(struct smb_request *req)
1802 connection_struct *conn = req->conn;
1807 /* Breakout the oplock request bits so we can set the
1808 reply bits separately. */
1809 int ex_oplock_request;
1810 int core_oplock_request;
1813 int smb_sattr = SVAL(req->vwv+4, 0);
1814 uint32 smb_time = make_unix_date3(req->vwv+6);
1819 SMB_STRUCT_STAT sbuf;
1823 uint64_t allocation_size;
1824 ssize_t retval = -1;
1827 uint32 create_disposition;
1828 uint32 create_options = 0;
1829 TALLOC_CTX *ctx = talloc_tos();
1831 START_PROFILE(SMBopenX);
1833 if (req->wct < 15) {
1834 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1835 END_PROFILE(SMBopenX);
1839 SET_STAT_INVALID(sbuf);
1841 open_flags = SVAL(req->vwv+2, 0);
1842 deny_mode = SVAL(req->vwv+3, 0);
1843 smb_attr = SVAL(req->vwv+5, 0);
1844 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1845 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1846 oplock_request = ex_oplock_request | core_oplock_request;
1847 smb_ofun = SVAL(req->vwv+8, 0);
1848 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1850 /* If it's an IPC, pass off the pipe handler. */
1852 if (lp_nt_pipe_support()) {
1853 reply_open_pipe_and_X(conn, req);
1855 reply_doserror(req, ERRSRV, ERRaccess);
1857 END_PROFILE(SMBopenX);
1861 /* XXXX we need to handle passed times, sattr and flags */
1862 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1863 STR_TERMINATE, &status);
1864 if (!NT_STATUS_IS_OK(status)) {
1865 reply_nterror(req, status);
1866 END_PROFILE(SMBopenX);
1870 if (!map_open_params_to_ntcreate(
1871 fname, deny_mode, smb_ofun, &access_mask,
1872 &share_mode, &create_disposition, &create_options)) {
1873 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1874 END_PROFILE(SMBopenX);
1878 status = SMB_VFS_CREATE_FILE(
1881 0, /* root_dir_fid */
1883 CFF_DOS_PATH, /* create_file_flags */
1884 access_mask, /* access_mask */
1885 share_mode, /* share_access */
1886 create_disposition, /* create_disposition*/
1887 create_options, /* create_options */
1888 smb_attr, /* file_attributes */
1889 oplock_request, /* oplock_request */
1890 0, /* allocation_size */
1894 &smb_action, /* pinfo */
1897 if (!NT_STATUS_IS_OK(status)) {
1898 END_PROFILE(SMBopenX);
1899 if (open_was_deferred(req->mid)) {
1900 /* We have re-scheduled this call. */
1903 reply_openerror(req, status);
1907 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1908 if the file is truncated or created. */
1909 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1910 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1911 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1912 close_file(req, fsp, ERROR_CLOSE);
1913 reply_nterror(req, NT_STATUS_DISK_FULL);
1914 END_PROFILE(SMBopenX);
1917 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1919 close_file(req, fsp, ERROR_CLOSE);
1920 reply_nterror(req, NT_STATUS_DISK_FULL);
1921 END_PROFILE(SMBopenX);
1924 sbuf.st_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
1927 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1928 mtime = sbuf.st_mtime;
1930 close_file(req, fsp, ERROR_CLOSE);
1931 reply_doserror(req, ERRDOS, ERRnoaccess);
1932 END_PROFILE(SMBopenX);
1936 /* If the caller set the extended oplock request bit
1937 and we granted one (by whatever means) - set the
1938 correct bit for extended oplock reply.
1941 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1942 smb_action |= EXTENDED_OPLOCK_GRANTED;
1945 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1946 smb_action |= EXTENDED_OPLOCK_GRANTED;
1949 /* If the caller set the core oplock request bit
1950 and we granted one (by whatever means) - set the
1951 correct bit for core oplock reply.
1954 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1955 reply_outbuf(req, 19, 0);
1957 reply_outbuf(req, 15, 0);
1960 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1961 SCVAL(req->outbuf, smb_flg,
1962 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1965 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1966 SCVAL(req->outbuf, smb_flg,
1967 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1970 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1971 SSVAL(req->outbuf,smb_vwv3,fattr);
1972 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1973 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1975 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1977 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1978 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1979 SSVAL(req->outbuf,smb_vwv11,smb_action);
1981 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1982 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1985 END_PROFILE(SMBopenX);
1990 /****************************************************************************
1991 Reply to a SMBulogoffX.
1992 ****************************************************************************/
1994 void reply_ulogoffX(struct smb_request *req)
1998 START_PROFILE(SMBulogoffX);
2000 vuser = get_valid_user_struct(req->vuid);
2003 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2007 /* in user level security we are supposed to close any files
2008 open by this user */
2009 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2010 file_close_user(req->vuid);
2013 invalidate_vuid(req->vuid);
2015 reply_outbuf(req, 2, 0);
2017 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2019 END_PROFILE(SMBulogoffX);
2023 /****************************************************************************
2024 Reply to a mknew or a create.
2025 ****************************************************************************/
2027 void reply_mknew(struct smb_request *req)
2029 connection_struct *conn = req->conn;
2032 struct smb_file_time ft;
2034 int oplock_request = 0;
2035 SMB_STRUCT_STAT sbuf;
2037 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2038 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2039 uint32 create_disposition;
2040 uint32 create_options = 0;
2041 TALLOC_CTX *ctx = talloc_tos();
2043 START_PROFILE(SMBcreate);
2045 SET_STAT_INVALID(sbuf);
2048 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2049 END_PROFILE(SMBcreate);
2053 fattr = SVAL(req->vwv+0, 0);
2054 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2057 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2059 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2060 STR_TERMINATE, &status);
2061 if (!NT_STATUS_IS_OK(status)) {
2062 reply_nterror(req, status);
2063 END_PROFILE(SMBcreate);
2067 if (fattr & aVOLID) {
2068 DEBUG(0,("Attempt to create file (%s) with volid set - "
2069 "please report this\n", fname));
2072 if(req->cmd == SMBmknew) {
2073 /* We should fail if file exists. */
2074 create_disposition = FILE_CREATE;
2076 /* Create if file doesn't exist, truncate if it does. */
2077 create_disposition = FILE_OVERWRITE_IF;
2080 status = SMB_VFS_CREATE_FILE(
2083 0, /* root_dir_fid */
2085 CFF_DOS_PATH, /* create_file_flags */
2086 access_mask, /* access_mask */
2087 share_mode, /* share_access */
2088 create_disposition, /* create_disposition*/
2089 create_options, /* create_options */
2090 fattr, /* file_attributes */
2091 oplock_request, /* oplock_request */
2092 0, /* allocation_size */
2099 if (!NT_STATUS_IS_OK(status)) {
2100 END_PROFILE(SMBcreate);
2101 if (open_was_deferred(req->mid)) {
2102 /* We have re-scheduled this call. */
2105 reply_openerror(req, status);
2109 ft.atime = get_atimespec(&sbuf); /* atime. */
2110 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true);
2111 if (!NT_STATUS_IS_OK(status)) {
2112 END_PROFILE(SMBcreate);
2113 reply_openerror(req, status);
2117 reply_outbuf(req, 1, 0);
2118 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2120 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2121 SCVAL(req->outbuf,smb_flg,
2122 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2125 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2126 SCVAL(req->outbuf,smb_flg,
2127 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2130 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2131 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2132 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2134 END_PROFILE(SMBcreate);
2138 /****************************************************************************
2139 Reply to a create temporary file.
2140 ****************************************************************************/
2142 void reply_ctemp(struct smb_request *req)
2144 connection_struct *conn = req->conn;
2150 SMB_STRUCT_STAT sbuf;
2153 TALLOC_CTX *ctx = talloc_tos();
2155 START_PROFILE(SMBctemp);
2158 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2159 END_PROFILE(SMBctemp);
2163 fattr = SVAL(req->vwv+0, 0);
2164 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2166 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2167 STR_TERMINATE, &status);
2168 if (!NT_STATUS_IS_OK(status)) {
2169 reply_nterror(req, status);
2170 END_PROFILE(SMBctemp);
2174 fname = talloc_asprintf(ctx,
2178 fname = talloc_strdup(ctx, "TMXXXXXX");
2182 reply_nterror(req, NT_STATUS_NO_MEMORY);
2183 END_PROFILE(SMBctemp);
2187 status = resolve_dfspath(ctx, conn,
2188 req->flags2 & FLAGS2_DFS_PATHNAMES,
2191 if (!NT_STATUS_IS_OK(status)) {
2192 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2193 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2194 ERRSRV, ERRbadpath);
2195 END_PROFILE(SMBctemp);
2198 reply_nterror(req, status);
2199 END_PROFILE(SMBctemp);
2203 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
2204 if (!NT_STATUS_IS_OK(status)) {
2205 reply_nterror(req, status);
2206 END_PROFILE(SMBctemp);
2210 status = check_name(conn, fname);
2211 if (!NT_STATUS_IS_OK(status)) {
2212 reply_nterror(req, status);
2213 END_PROFILE(SMBctemp);
2217 tmpfd = mkstemp(fname);
2219 reply_unixerror(req, ERRDOS, ERRnoaccess);
2220 END_PROFILE(SMBctemp);
2224 SET_STAT_INVALID(sbuf);
2225 SMB_VFS_STAT(conn,fname,&sbuf);
2227 /* We should fail if file does not exist. */
2228 status = SMB_VFS_CREATE_FILE(
2231 0, /* root_dir_fid */
2233 0, /* create_file_flags */
2234 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2235 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2236 FILE_OPEN, /* create_disposition*/
2237 0, /* create_options */
2238 fattr, /* file_attributes */
2239 oplock_request, /* oplock_request */
2240 0, /* allocation_size */
2247 /* close fd from mkstemp() */
2250 if (!NT_STATUS_IS_OK(status)) {
2251 if (open_was_deferred(req->mid)) {
2252 /* We have re-scheduled this call. */
2253 END_PROFILE(SMBctemp);
2256 reply_openerror(req, status);
2257 END_PROFILE(SMBctemp);
2261 reply_outbuf(req, 1, 0);
2262 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2264 /* the returned filename is relative to the directory */
2265 s = strrchr_m(fsp->fsp_name, '/');
2273 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2274 thing in the byte section. JRA */
2275 SSVALS(p, 0, -1); /* what is this? not in spec */
2277 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2279 reply_nterror(req, NT_STATUS_NO_MEMORY);
2280 END_PROFILE(SMBctemp);
2284 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2285 SCVAL(req->outbuf, smb_flg,
2286 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2289 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2290 SCVAL(req->outbuf, smb_flg,
2291 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2294 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2295 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2296 fsp->fh->fd, (unsigned int)sbuf.st_mode ) );
2298 END_PROFILE(SMBctemp);
2302 /*******************************************************************
2303 Check if a user is allowed to rename a file.
2304 ********************************************************************/
2306 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2307 uint16 dirtype, SMB_STRUCT_STAT *pst)
2311 if (!CAN_WRITE(conn)) {
2312 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2315 fmode = dos_mode(conn, fsp->fsp_name, pst);
2316 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2317 return NT_STATUS_NO_SUCH_FILE;
2320 if (S_ISDIR(pst->st_mode)) {
2321 if (fsp->posix_open) {
2322 return NT_STATUS_OK;
2325 /* If no pathnames are open below this
2326 directory, allow the rename. */
2328 if (file_find_subpath(fsp)) {
2329 return NT_STATUS_ACCESS_DENIED;
2331 return NT_STATUS_OK;
2334 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2335 return NT_STATUS_OK;
2338 return NT_STATUS_ACCESS_DENIED;
2341 /*******************************************************************
2342 * unlink a file with all relevant access checks
2343 *******************************************************************/
2345 static NTSTATUS do_unlink(connection_struct *conn,
2346 struct smb_request *req,
2350 SMB_STRUCT_STAT sbuf;
2353 uint32 dirtype_orig = dirtype;
2356 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2358 if (!CAN_WRITE(conn)) {
2359 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2362 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2363 return map_nt_error_from_unix(errno);
2366 fattr = dos_mode(conn,fname,&sbuf);
2368 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2369 dirtype = aDIR|aARCH|aRONLY;
2372 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2374 return NT_STATUS_NO_SUCH_FILE;
2377 if (!dir_check_ftype(conn, fattr, dirtype)) {
2379 return NT_STATUS_FILE_IS_A_DIRECTORY;
2381 return NT_STATUS_NO_SUCH_FILE;
2384 if (dirtype_orig & 0x8000) {
2385 /* These will never be set for POSIX. */
2386 return NT_STATUS_NO_SUCH_FILE;
2390 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2391 return NT_STATUS_FILE_IS_A_DIRECTORY;
2394 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2395 return NT_STATUS_NO_SUCH_FILE;
2398 if (dirtype & 0xFF00) {
2399 /* These will never be set for POSIX. */
2400 return NT_STATUS_NO_SUCH_FILE;
2405 return NT_STATUS_NO_SUCH_FILE;
2408 /* Can't delete a directory. */
2410 return NT_STATUS_FILE_IS_A_DIRECTORY;
2415 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2416 return NT_STATUS_OBJECT_NAME_INVALID;
2417 #endif /* JRATEST */
2419 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2421 On a Windows share, a file with read-only dosmode can be opened with
2422 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2423 fails with NT_STATUS_CANNOT_DELETE error.
2425 This semantic causes a problem that a user can not
2426 rename a file with read-only dosmode on a Samba share
2427 from a Windows command prompt (i.e. cmd.exe, but can rename
2428 from Windows Explorer).
2431 if (!lp_delete_readonly(SNUM(conn))) {
2432 if (fattr & aRONLY) {
2433 return NT_STATUS_CANNOT_DELETE;
2437 /* On open checks the open itself will check the share mode, so
2438 don't do it here as we'll get it wrong. */
2440 status = SMB_VFS_CREATE_FILE
2443 0, /* root_dir_fid */
2445 0, /* create_file_flags */
2446 DELETE_ACCESS, /* access_mask */
2447 FILE_SHARE_NONE, /* share_access */
2448 FILE_OPEN, /* create_disposition*/
2449 FILE_NON_DIRECTORY_FILE, /* create_options */
2450 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2451 0, /* oplock_request */
2452 0, /* allocation_size */
2459 if (!NT_STATUS_IS_OK(status)) {
2460 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2461 nt_errstr(status)));
2465 /* The set is across all open files on this dev/inode pair. */
2466 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2467 close_file(req, fsp, NORMAL_CLOSE);
2468 return NT_STATUS_ACCESS_DENIED;
2471 return close_file(req, fsp, NORMAL_CLOSE);
2474 /****************************************************************************
2475 The guts of the unlink command, split out so it may be called by the NT SMB
2477 ****************************************************************************/
2479 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2480 uint32 dirtype, const char *name_in, bool has_wild)
2482 const char *directory = NULL;
2487 NTSTATUS status = NT_STATUS_OK;
2488 SMB_STRUCT_STAT sbuf, st;
2489 TALLOC_CTX *ctx = talloc_tos();
2491 status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
2492 if (!NT_STATUS_IS_OK(status)) {
2496 p = strrchr_m(name,'/');
2498 directory = talloc_strdup(ctx, ".");
2500 return NT_STATUS_NO_MEMORY;
2510 * We should only check the mangled cache
2511 * here if unix_convert failed. This means
2512 * that the path in 'mask' doesn't exist
2513 * on the file system and so we need to look
2514 * for a possible mangle. This patch from
2515 * Tine Smukavec <valentin.smukavec@hermes.si>.
2518 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
2519 char *new_mask = NULL;
2520 mangle_lookup_name_from_8_3(ctx,
2530 directory = talloc_asprintf(ctx,
2535 return NT_STATUS_NO_MEMORY;
2538 dirtype = FILE_ATTRIBUTE_NORMAL;
2541 status = check_name(conn, directory);
2542 if (!NT_STATUS_IS_OK(status)) {
2546 status = do_unlink(conn, req, directory, dirtype);
2547 if (!NT_STATUS_IS_OK(status)) {
2553 struct smb_Dir *dir_hnd = NULL;
2557 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2558 return NT_STATUS_OBJECT_NAME_INVALID;
2561 if (strequal(mask,"????????.???")) {
2566 status = check_name(conn, directory);
2567 if (!NT_STATUS_IS_OK(status)) {
2571 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2573 if (dir_hnd == NULL) {
2574 return map_nt_error_from_unix(errno);
2577 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2578 the pattern matches against the long name, otherwise the short name
2579 We don't implement this yet XXXX
2582 status = NT_STATUS_NO_SUCH_FILE;
2584 while ((dname = ReadDirName(dir_hnd, &offset, &st))) {
2587 if (!is_visible_file(conn, directory, dname, &st,
2593 /* Quick check for "." and ".." */
2594 if (ISDOT(dname) || ISDOTDOT(dname)) {
2598 if(!mask_match(dname, mask, conn->case_sensitive)) {
2602 fname = talloc_asprintf(ctx, "%s/%s",
2606 return NT_STATUS_NO_MEMORY;
2609 status = check_name(conn, fname);
2610 if (!NT_STATUS_IS_OK(status)) {
2611 TALLOC_FREE(dir_hnd);
2615 status = do_unlink(conn, req, fname, dirtype);
2616 if (!NT_STATUS_IS_OK(status)) {
2622 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2627 TALLOC_FREE(dir_hnd);
2630 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2631 status = map_nt_error_from_unix(errno);
2637 /****************************************************************************
2639 ****************************************************************************/
2641 void reply_unlink(struct smb_request *req)
2643 connection_struct *conn = req->conn;
2647 bool path_contains_wcard = False;
2648 TALLOC_CTX *ctx = talloc_tos();
2650 START_PROFILE(SMBunlink);
2653 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2654 END_PROFILE(SMBunlink);
2658 dirtype = SVAL(req->vwv+0, 0);
2660 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2661 STR_TERMINATE, &status,
2662 &path_contains_wcard);
2663 if (!NT_STATUS_IS_OK(status)) {
2664 reply_nterror(req, status);
2665 END_PROFILE(SMBunlink);
2669 status = resolve_dfspath_wcard(ctx, conn,
2670 req->flags2 & FLAGS2_DFS_PATHNAMES,
2673 &path_contains_wcard);
2674 if (!NT_STATUS_IS_OK(status)) {
2675 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2676 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2677 ERRSRV, ERRbadpath);
2678 END_PROFILE(SMBunlink);
2681 reply_nterror(req, status);
2682 END_PROFILE(SMBunlink);
2686 DEBUG(3,("reply_unlink : %s\n",name));
2688 status = unlink_internals(conn, req, dirtype, name,
2689 path_contains_wcard);
2690 if (!NT_STATUS_IS_OK(status)) {
2691 if (open_was_deferred(req->mid)) {
2692 /* We have re-scheduled this call. */
2693 END_PROFILE(SMBunlink);
2696 reply_nterror(req, status);
2697 END_PROFILE(SMBunlink);
2701 reply_outbuf(req, 0, 0);
2702 END_PROFILE(SMBunlink);
2707 /****************************************************************************
2709 ****************************************************************************/
2711 static void fail_readraw(void)
2713 const char *errstr = talloc_asprintf(talloc_tos(),
2714 "FAIL ! reply_readbraw: socket write fail (%s)",
2719 exit_server_cleanly(errstr);
2722 /****************************************************************************
2723 Fake (read/write) sendfile. Returns -1 on read or write fail.
2724 ****************************************************************************/
2726 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2730 size_t tosend = nread;
2737 bufsize = MIN(nread, 65536);
2739 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2743 while (tosend > 0) {
2747 if (tosend > bufsize) {
2752 ret = read_file(fsp,buf,startpos,cur_read);
2758 /* If we had a short read, fill with zeros. */
2759 if (ret < cur_read) {
2760 memset(buf, '\0', cur_read - ret);
2763 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2768 startpos += cur_read;
2772 return (ssize_t)nread;
2775 #if defined(WITH_SENDFILE)
2776 /****************************************************************************
2777 Deal with the case of sendfile reading less bytes from the file than
2778 requested. Fill with zeros (all we can do).
2779 ****************************************************************************/
2781 static void sendfile_short_send(files_struct *fsp,
2786 if (nread < headersize) {
2787 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2788 "header for file %s (%s). Terminating\n",
2789 fsp->fsp_name, strerror(errno) ));
2790 exit_server_cleanly("sendfile_short_send failed");
2793 nread -= headersize;
2795 if (nread < smb_maxcnt) {
2796 char *buf = SMB_CALLOC_ARRAY(char, 1024);
2798 exit_server_cleanly("sendfile_short_send: "
2802 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2803 "with zeros !\n", fsp->fsp_name));
2805 while (nread < smb_maxcnt) {
2807 * We asked for the real file size and told sendfile
2808 * to not go beyond the end of the file. But it can
2809 * happen that in between our fstat call and the
2810 * sendfile call the file was truncated. This is very
2811 * bad because we have already announced the larger
2812 * number of bytes to the client.
2814 * The best we can do now is to send 0-bytes, just as
2815 * a read from a hole in a sparse file would do.
2817 * This should happen rarely enough that I don't care
2818 * about efficiency here :-)
2822 to_write = MIN(sizeof(buf), smb_maxcnt - nread);
2823 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2824 exit_server_cleanly("sendfile_short_send: "
2825 "write_data failed");
2832 #endif /* defined WITH_SENDFILE */
2834 /****************************************************************************
2835 Return a readbraw error (4 bytes of zero).
2836 ****************************************************************************/
2838 static void reply_readbraw_error(void)
2842 if (write_data(smbd_server_fd(),header,4) != 4) {
2847 /****************************************************************************
2848 Use sendfile in readbraw.
2849 ****************************************************************************/
2851 static void send_file_readbraw(connection_struct *conn,
2852 struct smb_request *req,
2858 char *outbuf = NULL;
2861 #if defined(WITH_SENDFILE)
2863 * We can only use sendfile on a non-chained packet
2864 * but we can use on a non-oplocked file. tridge proved this
2865 * on a train in Germany :-). JRA.
2866 * reply_readbraw has already checked the length.
2869 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2870 (fsp->wcp == NULL) &&
2871 lp_use_sendfile(SNUM(conn), smbd_server_conn->signing_state) ) {
2872 ssize_t sendfile_read = -1;
2874 DATA_BLOB header_blob;
2876 _smb_setlen(header,nread);
2877 header_blob = data_blob_const(header, 4);
2879 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2880 &header_blob, startpos, nread)) == -1) {
2881 /* Returning ENOSYS means no data at all was sent.
2882 * Do this as a normal read. */
2883 if (errno == ENOSYS) {
2884 goto normal_readbraw;
2888 * Special hack for broken Linux with no working sendfile. If we
2889 * return EINTR we sent the header but not the rest of the data.
2890 * Fake this up by doing read/write calls.
2892 if (errno == EINTR) {
2893 /* Ensure we don't do this again. */
2894 set_use_sendfile(SNUM(conn), False);
2895 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2897 if (fake_sendfile(fsp, startpos, nread) == -1) {
2898 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2899 fsp->fsp_name, strerror(errno) ));
2900 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2905 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2906 fsp->fsp_name, strerror(errno) ));
2907 exit_server_cleanly("send_file_readbraw sendfile failed");
2908 } else if (sendfile_read == 0) {
2910 * Some sendfile implementations return 0 to indicate
2911 * that there was a short read, but nothing was
2912 * actually written to the socket. In this case,
2913 * fallback to the normal read path so the header gets
2914 * the correct byte count.
2916 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2917 "bytes falling back to the normal read: "
2918 "%s\n", fsp->fsp_name));
2919 goto normal_readbraw;
2922 /* Deal with possible short send. */
2923 if (sendfile_read != 4+nread) {
2924 sendfile_short_send(fsp, sendfile_read, 4, nread);
2932 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2934 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2935 (unsigned)(nread+4)));
2936 reply_readbraw_error();
2941 ret = read_file(fsp,outbuf+4,startpos,nread);
2942 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2951 _smb_setlen(outbuf,ret);
2952 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2955 TALLOC_FREE(outbuf);
2958 /****************************************************************************
2959 Reply to a readbraw (core+ protocol).
2960 ****************************************************************************/
2962 void reply_readbraw(struct smb_request *req)
2964 connection_struct *conn = req->conn;
2965 ssize_t maxcount,mincount;
2969 struct lock_struct lock;
2973 START_PROFILE(SMBreadbraw);
2975 if (srv_is_signing_active(smbd_server_conn) ||
2976 is_encrypted_packet(req->inbuf)) {
2977 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2978 "raw reads/writes are disallowed.");
2982 reply_readbraw_error();
2983 END_PROFILE(SMBreadbraw);
2988 * Special check if an oplock break has been issued
2989 * and the readraw request croses on the wire, we must
2990 * return a zero length response here.
2993 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2996 * We have to do a check_fsp by hand here, as
2997 * we must always return 4 zero bytes on error,
3001 if (!fsp || !conn || conn != fsp->conn ||
3002 req->vuid != fsp->vuid ||
3003 fsp->is_directory || fsp->fh->fd == -1) {
3005 * fsp could be NULL here so use the value from the packet. JRA.
3007 DEBUG(3,("reply_readbraw: fnum %d not valid "
3009 (int)SVAL(req->vwv+0, 0)));
3010 reply_readbraw_error();
3011 END_PROFILE(SMBreadbraw);
3015 /* Do a "by hand" version of CHECK_READ. */
3016 if (!(fsp->can_read ||
3017 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3018 (fsp->access_mask & FILE_EXECUTE)))) {
3019 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3020 (int)SVAL(req->vwv+0, 0)));
3021 reply_readbraw_error();
3022 END_PROFILE(SMBreadbraw);
3026 flush_write_cache(fsp, READRAW_FLUSH);
3028 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3029 if(req->wct == 10) {
3031 * This is a large offset (64 bit) read.
3033 #ifdef LARGE_SMB_OFF_T
3035 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3037 #else /* !LARGE_SMB_OFF_T */
3040 * Ensure we haven't been sent a >32 bit offset.
3043 if(IVAL(req->vwv+8, 0) != 0) {
3044 DEBUG(0,("reply_readbraw: large offset "
3045 "(%x << 32) used and we don't support "
3046 "64 bit offsets.\n",
3047 (unsigned int)IVAL(req->vwv+8, 0) ));
3048 reply_readbraw_error();
3049 END_PROFILE(SMBreadbraw);
3053 #endif /* LARGE_SMB_OFF_T */
3056 DEBUG(0,("reply_readbraw: negative 64 bit "
3057 "readraw offset (%.0f) !\n",
3058 (double)startpos ));
3059 reply_readbraw_error();
3060 END_PROFILE(SMBreadbraw);
3065 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3066 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3068 /* ensure we don't overrun the packet size */
3069 maxcount = MIN(65535,maxcount);
3071 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3072 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3075 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3076 reply_readbraw_error();
3077 END_PROFILE(SMBreadbraw);
3081 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3085 if (startpos >= size) {
3088 nread = MIN(maxcount,(size - startpos));
3091 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3092 if (nread < mincount)
3096 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3097 "min=%lu nread=%lu\n",
3098 fsp->fnum, (double)startpos,
3099 (unsigned long)maxcount,
3100 (unsigned long)mincount,
3101 (unsigned long)nread ) );
3103 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3105 DEBUG(5,("reply_readbraw finished\n"));
3107 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3109 END_PROFILE(SMBreadbraw);
3114 #define DBGC_CLASS DBGC_LOCKING
3116 /****************************************************************************
3117 Reply to a lockread (core+ protocol).
3118 ****************************************************************************/
3120 void reply_lockread(struct smb_request *req)
3122 connection_struct *conn = req->conn;
3129 struct byte_range_lock *br_lck = NULL;
3132 START_PROFILE(SMBlockread);
3135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3136 END_PROFILE(SMBlockread);
3140 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3142 if (!check_fsp(conn, req, fsp)) {
3143 END_PROFILE(SMBlockread);
3147 if (!CHECK_READ(fsp,req)) {
3148 reply_doserror(req, ERRDOS, ERRbadaccess);
3149 END_PROFILE(SMBlockread);
3153 numtoread = SVAL(req->vwv+1, 0);
3154 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3156 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3158 reply_outbuf(req, 5, numtoread + 3);
3160 data = smb_buf(req->outbuf) + 3;
3163 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3164 * protocol request that predates the read/write lock concept.
3165 * Thus instead of asking for a read lock here we need to ask
3166 * for a write lock. JRA.
3167 * Note that the requested lock size is unaffected by max_recv.
3170 br_lck = do_lock(smbd_messaging_context(),
3173 (uint64_t)numtoread,
3177 False, /* Non-blocking lock. */
3181 TALLOC_FREE(br_lck);
3183 if (NT_STATUS_V(status)) {
3184 reply_nterror(req, status);
3185 END_PROFILE(SMBlockread);
3190 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3193 if (numtoread > max_recv) {
3194 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3195 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3196 (unsigned int)numtoread, (unsigned int)max_recv ));
3197 numtoread = MIN(numtoread,max_recv);
3199 nread = read_file(fsp,data,startpos,numtoread);
3202 reply_unixerror(req, ERRDOS, ERRnoaccess);
3203 END_PROFILE(SMBlockread);
3207 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3209 SSVAL(req->outbuf,smb_vwv0,nread);
3210 SSVAL(req->outbuf,smb_vwv5,nread+3);
3211 p = smb_buf(req->outbuf);
3212 SCVAL(p,0,0); /* pad byte. */
3215 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3216 fsp->fnum, (int)numtoread, (int)nread));
3218 END_PROFILE(SMBlockread);
3223 #define DBGC_CLASS DBGC_ALL
3225 /****************************************************************************
3227 ****************************************************************************/
3229 void reply_read(struct smb_request *req)
3231 connection_struct *conn = req->conn;
3238 struct lock_struct lock;
3240 START_PROFILE(SMBread);
3243 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3244 END_PROFILE(SMBread);
3248 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3250 if (!check_fsp(conn, req, fsp)) {
3251 END_PROFILE(SMBread);
3255 if (!CHECK_READ(fsp,req)) {
3256 reply_doserror(req, ERRDOS, ERRbadaccess);
3257 END_PROFILE(SMBread);
3261 numtoread = SVAL(req->vwv+1, 0);
3262 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3264 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3267 * The requested read size cannot be greater than max_recv. JRA.
3269 if (numtoread > max_recv) {
3270 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3271 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3272 (unsigned int)numtoread, (unsigned int)max_recv ));
3273 numtoread = MIN(numtoread,max_recv);
3276 reply_outbuf(req, 5, numtoread+3);
3278 data = smb_buf(req->outbuf) + 3;
3280 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3281 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3284 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3285 reply_doserror(req, ERRDOS,ERRlock);
3286 END_PROFILE(SMBread);
3291 nread = read_file(fsp,data,startpos,numtoread);
3294 reply_unixerror(req, ERRDOS,ERRnoaccess);
3298 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3300 SSVAL(req->outbuf,smb_vwv0,nread);
3301 SSVAL(req->outbuf,smb_vwv5,nread+3);
3302 SCVAL(smb_buf(req->outbuf),0,1);
3303 SSVAL(smb_buf(req->outbuf),1,nread);
3305 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3306 fsp->fnum, (int)numtoread, (int)nread ) );
3309 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3311 END_PROFILE(SMBread);
3315 /****************************************************************************
3317 ****************************************************************************/
3319 static int setup_readX_header(struct smb_request *req, char *outbuf,
3325 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3326 data = smb_buf(outbuf);
3328 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3330 SCVAL(outbuf,smb_vwv0,0xFF);
3331 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3332 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3333 SSVAL(outbuf,smb_vwv6,
3335 + 1 /* the wct field */
3336 + 12 * sizeof(uint16_t) /* vwv */
3337 + 2); /* the buflen field */
3338 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3339 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3340 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3341 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3345 /****************************************************************************
3346 Reply to a read and X - possibly using sendfile.
3347 ****************************************************************************/
3349 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3350 files_struct *fsp, SMB_OFF_T startpos,
3353 SMB_STRUCT_STAT sbuf;
3356 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3357 reply_unixerror(req, ERRDOS, ERRnoaccess);
3361 if (!S_ISREG(sbuf.st_mode) || (startpos > sbuf.st_size)
3362 || (smb_maxcnt > (sbuf.st_size - startpos))) {
3364 * We already know that we would do a short read, so don't
3365 * try the sendfile() path.
3367 goto nosendfile_read;
3370 #if defined(WITH_SENDFILE)
3372 * We can only use sendfile on a non-chained packet
3373 * but we can use on a non-oplocked file. tridge proved this
3374 * on a train in Germany :-). JRA.
3377 if (!req_is_in_chain(req) &&
3378 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3379 (fsp->wcp == NULL) &&
3380 lp_use_sendfile(SNUM(conn), smbd_server_conn->signing_state) ) {
3381 uint8 headerbuf[smb_size + 12 * 2];
3385 * Set up the packet header before send. We
3386 * assume here the sendfile will work (get the
3387 * correct amount of data).
3390 header = data_blob_const(headerbuf, sizeof(headerbuf));
3392 construct_reply_common_req(req, (char *)headerbuf);
3393 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3395 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3396 /* Returning ENOSYS means no data at all was sent.
3397 Do this as a normal read. */
3398 if (errno == ENOSYS) {
3403 * Special hack for broken Linux with no working sendfile. If we
3404 * return EINTR we sent the header but not the rest of the data.
3405 * Fake this up by doing read/write calls.
3408 if (errno == EINTR) {
3409 /* Ensure we don't do this again. */
3410 set_use_sendfile(SNUM(conn), False);
3411 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3412 nread = fake_sendfile(fsp, startpos,
3415 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3416 fsp->fsp_name, strerror(errno) ));
3417 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3419 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3420 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3421 /* No outbuf here means successful sendfile. */
3422 TALLOC_FREE(req->outbuf);
3426 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3427 fsp->fsp_name, strerror(errno) ));
3428 exit_server_cleanly("send_file_readX sendfile failed");
3429 } else if (nread == 0) {
3431 * Some sendfile implementations return 0 to indicate
3432 * that there was a short read, but nothing was
3433 * actually written to the socket. In this case,
3434 * fallback to the normal read path so the header gets
3435 * the correct byte count.
3437 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3438 "falling back to the normal read: %s\n",
3443 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3444 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3446 /* Deal with possible short send. */
3447 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3448 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3451 /* No outbuf here means successful sendfile. */
3452 TALLOC_FREE(req->outbuf);
3453 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3454 SMB_PERFCOUNT_END(&req->pcd);
3462 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3463 uint8 headerbuf[smb_size + 2*12];
3465 construct_reply_common_req(req, (char *)headerbuf);
3466 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3468 /* Send out the header. */
3469 if (write_data(smbd_server_fd(), (char *)headerbuf,
3470 sizeof(headerbuf)) != sizeof(headerbuf)) {
3471 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3472 fsp->fsp_name, strerror(errno) ));
3473 exit_server_cleanly("send_file_readX sendfile failed");
3475 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3477 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3478 fsp->fsp_name, strerror(errno) ));
3479 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3481 TALLOC_FREE(req->outbuf);
3487 reply_outbuf(req, 12, smb_maxcnt);
3489 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3491 reply_unixerror(req, ERRDOS, ERRnoaccess);
3495 setup_readX_header(req, (char *)req->outbuf, nread);
3497 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3498 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3503 /****************************************************************************
3504 Reply to a read and X.
3505 ****************************************************************************/
3507 void reply_read_and_X(struct smb_request *req)
3509 connection_struct *conn = req->conn;
3513 struct lock_struct lock;
3514 bool big_readX = False;
3516 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3519 START_PROFILE(SMBreadX);
3521 if ((req->wct != 10) && (req->wct != 12)) {
3522 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3526 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3527 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3528 smb_maxcnt = SVAL(req->vwv+5, 0);
3530 /* If it's an IPC, pass off the pipe handler. */
3532 reply_pipe_read_and_X(req);
3533 END_PROFILE(SMBreadX);
3537 if (!check_fsp(conn, req, fsp)) {
3538 END_PROFILE(SMBreadX);
3542 if (!CHECK_READ(fsp,req)) {
3543 reply_doserror(req, ERRDOS,ERRbadaccess);
3544 END_PROFILE(SMBreadX);
3548 if (global_client_caps & CAP_LARGE_READX) {
3549 size_t upper_size = SVAL(req->vwv+7, 0);
3550 smb_maxcnt |= (upper_size<<16);
3551 if (upper_size > 1) {
3552 /* Can't do this on a chained packet. */
3553 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3554 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3555 END_PROFILE(SMBreadX);
3558 /* We currently don't do this on signed or sealed data. */
3559 if (srv_is_signing_active(smbd_server_conn) ||
3560 is_encrypted_packet(req->inbuf)) {
3561 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3562 END_PROFILE(SMBreadX);
3565 /* Is there room in the reply for this data ? */
3566 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3568 NT_STATUS_INVALID_PARAMETER);
3569 END_PROFILE(SMBreadX);
3576 if (req->wct == 12) {
3577 #ifdef LARGE_SMB_OFF_T
3579 * This is a large offset (64 bit) read.
3581 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3583 #else /* !LARGE_SMB_OFF_T */
3586 * Ensure we haven't been sent a >32 bit offset.
3589 if(IVAL(req->vwv+10, 0) != 0) {
3590 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3591 "used and we don't support 64 bit offsets.\n",
3592 (unsigned int)IVAL(req->vwv+10, 0) ));
3593 END_PROFILE(SMBreadX);
3594 reply_doserror(req, ERRDOS, ERRbadaccess);
3598 #endif /* LARGE_SMB_OFF_T */
3602 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3603 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3606 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3607 END_PROFILE(SMBreadX);
3608 reply_doserror(req, ERRDOS, ERRlock);
3613 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3617 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3620 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3622 END_PROFILE(SMBreadX);
3626 /****************************************************************************
3627 Error replies to writebraw must have smb_wct == 1. Fix this up.
3628 ****************************************************************************/
3630 void error_to_writebrawerr(struct smb_request *req)
3632 uint8 *old_outbuf = req->outbuf;
3634 reply_outbuf(req, 1, 0);
3636 memcpy(req->outbuf, old_outbuf, smb_size);
3637 TALLOC_FREE(old_outbuf);
3640 /****************************************************************************
3641 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3642 ****************************************************************************/
3644 void reply_writebraw(struct smb_request *req)
3646 connection_struct *conn = req->conn;
3649 ssize_t total_written=0;
3650 size_t numtowrite=0;
3656 struct lock_struct lock;
3659 START_PROFILE(SMBwritebraw);
3662 * If we ever reply with an error, it must have the SMB command
3663 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3666 SCVAL(req->inbuf,smb_com,SMBwritec);
3668 if (srv_is_signing_active(smbd_server_conn)) {
3669 END_PROFILE(SMBwritebraw);
3670 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3671 "raw reads/writes are disallowed.");
3674 if (req->wct < 12) {
3675 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3676 error_to_writebrawerr(req);
3677 END_PROFILE(SMBwritebraw);
3681 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3682 if (!check_fsp(conn, req, fsp)) {
3683 error_to_writebrawerr(req);
3684 END_PROFILE(SMBwritebraw);
3688 if (!CHECK_WRITE(fsp)) {
3689 reply_doserror(req, ERRDOS, ERRbadaccess);
3690 error_to_writebrawerr(req);
3691 END_PROFILE(SMBwritebraw);
3695 tcount = IVAL(req->vwv+1, 0);
3696 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3697 write_through = BITSETW(req->vwv+7,0);
3699 /* We have to deal with slightly different formats depending
3700 on whether we are using the core+ or lanman1.0 protocol */
3702 if(Protocol <= PROTOCOL_COREPLUS) {
3703 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3704 data = smb_buf(req->inbuf);
3706 numtowrite = SVAL(req->vwv+10, 0);
3707 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3710 /* Ensure we don't write bytes past the end of this packet. */
3711 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3712 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3713 error_to_writebrawerr(req);
3714 END_PROFILE(SMBwritebraw);
3718 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3719 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3722 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3723 reply_doserror(req, ERRDOS, ERRlock);
3724 error_to_writebrawerr(req);
3725 END_PROFILE(SMBwritebraw);
3730 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3733 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3734 "wrote=%d sync=%d\n",
3735 fsp->fnum, (double)startpos, (int)numtowrite,
3736 (int)nwritten, (int)write_through));
3738 if (nwritten < (ssize_t)numtowrite) {
3739 reply_unixerror(req, ERRHRD, ERRdiskfull);
3740 error_to_writebrawerr(req);
3744 total_written = nwritten;
3746 /* Allocate a buffer of 64k + length. */
3747 buf = TALLOC_ARRAY(NULL, char, 65540);
3749 reply_doserror(req, ERRDOS, ERRnomem);
3750 error_to_writebrawerr(req);
3754 /* Return a SMBwritebraw message to the redirector to tell
3755 * it to send more bytes */
3757 memcpy(buf, req->inbuf, smb_size);
3758 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3759 SCVAL(buf,smb_com,SMBwritebraw);
3760 SSVALS(buf,smb_vwv0,0xFFFF);
3762 if (!srv_send_smb(smbd_server_fd(),
3764 false, 0, /* no signing */
3765 IS_CONN_ENCRYPTED(conn),
3767 exit_server_cleanly("reply_writebraw: srv_send_smb "
3771 /* Now read the raw data into the buffer and write it */
3772 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3774 if (!NT_STATUS_IS_OK(status)) {
3775 exit_server_cleanly("secondary writebraw failed");
3778 /* Set up outbuf to return the correct size */
3779 reply_outbuf(req, 1, 0);
3781 if (numtowrite != 0) {
3783 if (numtowrite > 0xFFFF) {
3784 DEBUG(0,("reply_writebraw: Oversize secondary write "
3785 "raw requested (%u). Terminating\n",
3786 (unsigned int)numtowrite ));
3787 exit_server_cleanly("secondary writebraw failed");
3790 if (tcount > nwritten+numtowrite) {
3791 DEBUG(3,("reply_writebraw: Client overestimated the "
3793 (int)tcount,(int)nwritten,(int)numtowrite));
3796 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3798 if (!NT_STATUS_IS_OK(status)) {
3799 DEBUG(0,("reply_writebraw: Oversize secondary write "
3800 "raw read failed (%s). Terminating\n",
3801 nt_errstr(status)));
3802 exit_server_cleanly("secondary writebraw failed");
3805 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3806 if (nwritten == -1) {
3808 reply_unixerror(req, ERRHRD, ERRdiskfull);
3809 error_to_writebrawerr(req);
3813 if (nwritten < (ssize_t)numtowrite) {
3814 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3815 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3819 total_written += nwritten;
3824 SSVAL(req->outbuf,smb_vwv0,total_written);
3826 status = sync_file(conn, fsp, write_through);
3827 if (!NT_STATUS_IS_OK(status)) {
3828 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3829 fsp->fsp_name, nt_errstr(status) ));
3830 reply_nterror(req, status);
3831 error_to_writebrawerr(req);
3835 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3837 fsp->fnum, (double)startpos, (int)numtowrite,
3838 (int)total_written));
3840 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3842 /* We won't return a status if write through is not selected - this
3843 * follows what WfWg does */
3844 END_PROFILE(SMBwritebraw);
3846 if (!write_through && total_written==tcount) {
3848 #if RABBIT_PELLET_FIX
3850 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3851 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3854 if (!send_keepalive(smbd_server_fd())) {
3855 exit_server_cleanly("reply_writebraw: send of "
3856 "keepalive failed");
3859 TALLOC_FREE(req->outbuf);
3864 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3866 END_PROFILE(SMBwritebraw);
3871 #define DBGC_CLASS DBGC_LOCKING
3873 /****************************************************************************
3874 Reply to a writeunlock (core+).
3875 ****************************************************************************/
3877 void reply_writeunlock(struct smb_request *req)
3879 connection_struct *conn = req->conn;
3880 ssize_t nwritten = -1;
3884 NTSTATUS status = NT_STATUS_OK;
3886 struct lock_struct lock;
3888 START_PROFILE(SMBwriteunlock);
3891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3892 END_PROFILE(SMBwriteunlock);
3896 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3898 if (!check_fsp(conn, req, fsp)) {
3899 END_PROFILE(SMBwriteunlock);
3903 if (!CHECK_WRITE(fsp)) {
3904 reply_doserror(req, ERRDOS,ERRbadaccess);
3905 END_PROFILE(SMBwriteunlock);
3909 numtowrite = SVAL(req->vwv+1, 0);
3910 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3911 data = (const char *)req->buf + 3;
3914 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3915 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3918 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3919 reply_doserror(req, ERRDOS, ERRlock);
3920 END_PROFILE(SMBwriteunlock);
3925 /* The special X/Open SMB protocol handling of
3926 zero length writes is *NOT* done for
3928 if(numtowrite == 0) {
3931 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3934 status = sync_file(conn, fsp, False /* write through */);
3935 if (!NT_STATUS_IS_OK(status)) {
3936 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3937 fsp->fsp_name, nt_errstr(status) ));
3938 reply_nterror(req, status);
3942 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3943 reply_unixerror(req, ERRHRD, ERRdiskfull);
3948 status = do_unlock(smbd_messaging_context(),
3951 (uint64_t)numtowrite,
3955 if (NT_STATUS_V(status)) {
3956 reply_nterror(req, status);
3961 reply_outbuf(req, 1, 0);
3963 SSVAL(req->outbuf,smb_vwv0,nwritten);
3965 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3966 fsp->fnum, (int)numtowrite, (int)nwritten));
3970 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3973 END_PROFILE(SMBwriteunlock);
3978 #define DBGC_CLASS DBGC_ALL
3980 /****************************************************************************
3982 ****************************************************************************/
3984 void reply_write(struct smb_request *req)
3986 connection_struct *conn = req->conn;
3988 ssize_t nwritten = -1;
3992 struct lock_struct lock;
3995 START_PROFILE(SMBwrite);
3998 END_PROFILE(SMBwrite);
3999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4003 /* If it's an IPC, pass off the pipe handler. */
4005 reply_pipe_write(req);
4006 END_PROFILE(SMBwrite);
4010 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4012 if (!check_fsp(conn, req, fsp)) {
4013 END_PROFILE(SMBwrite);
4017 if (!CHECK_WRITE(fsp)) {
4018 reply_doserror(req, ERRDOS, ERRbadaccess);
4019 END_PROFILE(SMBwrite);
4023 numtowrite = SVAL(req->vwv+1, 0);
4024 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4025 data = (const char *)req->buf + 3;
4027 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4028 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4031 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4032 reply_doserror(req, ERRDOS, ERRlock);
4033 END_PROFILE(SMBwrite);
4038 * X/Open SMB protocol says that if smb_vwv1 is
4039 * zero then the file size should be extended or
4040 * truncated to the size given in smb_vwv[2-3].
4043 if(numtowrite == 0) {
4045 * This is actually an allocate call, and set EOF. JRA.
4047 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4049 reply_nterror(req, NT_STATUS_DISK_FULL);
4052 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4054 reply_nterror(req, NT_STATUS_DISK_FULL);
4057 trigger_write_time_update_immediate(fsp);
4059 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4062 status = sync_file(conn, fsp, False);
4063 if (!NT_STATUS_IS_OK(status)) {
4064 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4065 fsp->fsp_name, nt_errstr(status) ));
4066 reply_nterror(req, status);
4070 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4071 reply_unixerror(req, ERRHRD, ERRdiskfull);
4075 reply_outbuf(req, 1, 0);
4077 SSVAL(req->outbuf,smb_vwv0,nwritten);
4079 if (nwritten < (ssize_t)numtowrite) {
4080 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4081 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4084 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4087 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4089 END_PROFILE(SMBwrite);
4093 /****************************************************************************
4094 Ensure a buffer is a valid writeX for recvfile purposes.
4095 ****************************************************************************/
4097 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4098 (2*14) + /* word count (including bcc) */ \
4101 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4104 connection_struct *conn = NULL;
4105 unsigned int doff = 0;
4106 size_t len = smb_len_large(inbuf);
4108 if (is_encrypted_packet(inbuf)) {
4109 /* Can't do this on encrypted
4114 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4118 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4119 CVAL(inbuf,smb_wct) != 14) {
4120 DEBUG(10,("is_valid_writeX_buffer: chained or "
4121 "invalid word length.\n"));
4125 conn = conn_find(SVAL(inbuf, smb_tid));
4127 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4131 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4134 if (IS_PRINT(conn)) {
4135 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4138 doff = SVAL(inbuf,smb_vwv11);
4140 numtowrite = SVAL(inbuf,smb_vwv10);
4142 if (len > doff && len - doff > 0xFFFF) {
4143 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4146 if (numtowrite == 0) {
4147 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4151 /* Ensure the sizes match up. */
4152 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4153 /* no pad byte...old smbclient :-( */
4154 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4156 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4160 if (len - doff != numtowrite) {
4161 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4162 "len = %u, doff = %u, numtowrite = %u\n",
4165 (unsigned int)numtowrite ));
4169 DEBUG(10,("is_valid_writeX_buffer: true "
4170 "len = %u, doff = %u, numtowrite = %u\n",
4173 (unsigned int)numtowrite ));
4178 /****************************************************************************
4179 Reply to a write and X.
4180 ****************************************************************************/
4182 void reply_write_and_X(struct smb_request *req)
4184 connection_struct *conn = req->conn;
4186 struct lock_struct lock;
4191 unsigned int smb_doff;
4192 unsigned int smblen;
4196 START_PROFILE(SMBwriteX);
4198 if ((req->wct != 12) && (req->wct != 14)) {
4199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4200 END_PROFILE(SMBwriteX);
4204 numtowrite = SVAL(req->vwv+10, 0);
4205 smb_doff = SVAL(req->vwv+11, 0);
4206 smblen = smb_len(req->inbuf);
4208 if (req->unread_bytes > 0xFFFF ||
4209 (smblen > smb_doff &&
4210 smblen - smb_doff > 0xFFFF)) {
4211 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4214 if (req->unread_bytes) {
4215 /* Can't do a recvfile write on IPC$ */
4217 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4218 END_PROFILE(SMBwriteX);
4221 if (numtowrite != req->unread_bytes) {
4222 reply_doserror(req, ERRDOS, ERRbadmem);
4223 END_PROFILE(SMBwriteX);
4227 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4228 smb_doff + numtowrite > smblen) {
4229 reply_doserror(req, ERRDOS, ERRbadmem);
4230 END_PROFILE(SMBwriteX);
4235 /* If it's an IPC, pass off the pipe handler. */
4237 if (req->unread_bytes) {
4238 reply_doserror(req, ERRDOS, ERRbadmem);
4239 END_PROFILE(SMBwriteX);
4242 reply_pipe_write_and_X(req);
4243 END_PROFILE(SMBwriteX);
4247 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4248 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4249 write_through = BITSETW(req->vwv+7,0);
4251 if (!check_fsp(conn, req, fsp)) {
4252 END_PROFILE(SMBwriteX);
4256 if (!CHECK_WRITE(fsp)) {
4257 reply_doserror(req, ERRDOS, ERRbadaccess);
4258 END_PROFILE(SMBwriteX);
4262 data = smb_base(req->inbuf) + smb_doff;
4264 if(req->wct == 14) {
4265 #ifdef LARGE_SMB_OFF_T
4267 * This is a large offset (64 bit) write.
4269 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4271 #else /* !LARGE_SMB_OFF_T */
4274 * Ensure we haven't been sent a >32 bit offset.
4277 if(IVAL(req->vwv+12, 0) != 0) {
4278 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4279 "used and we don't support 64 bit offsets.\n",
4280 (unsigned int)IVAL(req->vwv+12, 0) ));
4281 reply_doserror(req, ERRDOS, ERRbadaccess);
4282 END_PROFILE(SMBwriteX);
4286 #endif /* LARGE_SMB_OFF_T */
4289 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4290 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4293 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4294 reply_doserror(req, ERRDOS, ERRlock);
4295 END_PROFILE(SMBwriteX);
4299 /* X/Open SMB protocol says that, unlike SMBwrite
4300 if the length is zero then NO truncation is
4301 done, just a write of zero. To truncate a file,
4304 if(numtowrite == 0) {
4308 if ((req->unread_bytes == 0) &&
4309 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4314 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4317 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4318 reply_unixerror(req, ERRHRD, ERRdiskfull);
4322 reply_outbuf(req, 6, 0);
4323 SSVAL(req->outbuf,smb_vwv2,nwritten);
4324 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4326 if (nwritten < (ssize_t)numtowrite) {
4327 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4328 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4331 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4332 fsp->fnum, (int)numtowrite, (int)nwritten));
4334 status = sync_file(conn, fsp, write_through);
4335 if (!NT_STATUS_IS_OK(status)) {
4336 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4337 fsp->fsp_name, nt_errstr(status) ));
4338 reply_nterror(req, status);
4342 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4344 END_PROFILE(SMBwriteX);
4349 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4351 END_PROFILE(SMBwriteX);
4355 /****************************************************************************
4357 ****************************************************************************/
4359 void reply_lseek(struct smb_request *req)
4361 connection_struct *conn = req->conn;
4367 START_PROFILE(SMBlseek);
4370 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4371 END_PROFILE(SMBlseek);
4375 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4377 if (!check_fsp(conn, req, fsp)) {
4381 flush_write_cache(fsp, SEEK_FLUSH);
4383 mode = SVAL(req->vwv+1, 0) & 3;
4384 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4385 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4394 res = fsp->fh->pos + startpos;
4405 if (umode == SEEK_END) {
4406 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4407 if(errno == EINVAL) {
4408 SMB_OFF_T current_pos = startpos;
4409 SMB_STRUCT_STAT sbuf;
4411 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4412 reply_unixerror(req, ERRDOS,
4414 END_PROFILE(SMBlseek);
4418 current_pos += sbuf.st_size;
4420 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4425 reply_unixerror(req, ERRDOS, ERRnoaccess);
4426 END_PROFILE(SMBlseek);
4433 reply_outbuf(req, 2, 0);
4434 SIVAL(req->outbuf,smb_vwv0,res);
4436 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4437 fsp->fnum, (double)startpos, (double)res, mode));
4439 END_PROFILE(SMBlseek);
4443 /****************************************************************************
4445 ****************************************************************************/
4447 void reply_flush(struct smb_request *req)
4449 connection_struct *conn = req->conn;
4453 START_PROFILE(SMBflush);
4456 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4460 fnum = SVAL(req->vwv+0, 0);
4461 fsp = file_fsp(req, fnum);
4463 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4468 file_sync_all(conn);
4470 NTSTATUS status = sync_file(conn, fsp, True);
4471 if (!NT_STATUS_IS_OK(status)) {
4472 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4473 fsp->fsp_name, nt_errstr(status) ));
4474 reply_nterror(req, status);
4475 END_PROFILE(SMBflush);
4480 reply_outbuf(req, 0, 0);
4482 DEBUG(3,("flush\n"));
4483 END_PROFILE(SMBflush);
4487 /****************************************************************************
4489 conn POINTER CAN BE NULL HERE !
4490 ****************************************************************************/
4492 void reply_exit(struct smb_request *req)
4494 START_PROFILE(SMBexit);
4496 file_close_pid(req->smbpid, req->vuid);
4498 reply_outbuf(req, 0, 0);
4500 DEBUG(3,("exit\n"));
4502 END_PROFILE(SMBexit);
4506 /****************************************************************************
4507 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4508 ****************************************************************************/
4510 void reply_close(struct smb_request *req)
4512 connection_struct *conn = req->conn;
4513 NTSTATUS status = NT_STATUS_OK;
4514 files_struct *fsp = NULL;
4515 START_PROFILE(SMBclose);
4518 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4519 END_PROFILE(SMBclose);
4523 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4526 * We can only use check_fsp if we know it's not a directory.
4529 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4530 reply_doserror(req, ERRDOS, ERRbadfid);
4531 END_PROFILE(SMBclose);
4535 if(fsp->is_directory) {
4537 * Special case - close NT SMB directory handle.
4539 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4540 status = close_file(req, fsp, NORMAL_CLOSE);
4544 * Close ordinary file.
4547 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4548 fsp->fh->fd, fsp->fnum,
4549 conn->num_files_open));
4552 * Take care of any time sent in the close.
4555 t = srv_make_unix_date3(req->vwv+1);
4556 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4559 * close_file() returns the unix errno if an error
4560 * was detected on close - normally this is due to
4561 * a disk full error. If not then it was probably an I/O error.
4564 status = close_file(req, fsp, NORMAL_CLOSE);
4567 if (!NT_STATUS_IS_OK(status)) {
4568 reply_nterror(req, status);
4569 END_PROFILE(SMBclose);
4573 reply_outbuf(req, 0, 0);
4574 END_PROFILE(SMBclose);
4578 /****************************************************************************
4579 Reply to a writeclose (Core+ protocol).
4580 ****************************************************************************/
4582 void reply_writeclose(struct smb_request *req)
4584 connection_struct *conn = req->conn;
4586 ssize_t nwritten = -1;
4587 NTSTATUS close_status = NT_STATUS_OK;
4590 struct timespec mtime;
4592 struct lock_struct lock;
4594 START_PROFILE(SMBwriteclose);
4597 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4598 END_PROFILE(SMBwriteclose);
4602 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4604 if (!check_fsp(conn, req, fsp)) {
4605 END_PROFILE(SMBwriteclose);
4608 if (!CHECK_WRITE(fsp)) {
4609 reply_doserror(req, ERRDOS,ERRbadaccess);
4610 END_PROFILE(SMBwriteclose);
4614 numtowrite = SVAL(req->vwv+1, 0);
4615 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4616 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4617 data = (const char *)req->buf + 1;
4620 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4621 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4624 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4625 reply_doserror(req, ERRDOS,ERRlock);
4626 END_PROFILE(SMBwriteclose);
4631 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4633 set_close_write_time(fsp, mtime);
4636 * More insanity. W2K only closes the file if writelen > 0.
4641 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4643 close_status = close_file(req, fsp, NORMAL_CLOSE);
4646 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4647 fsp->fnum, (int)numtowrite, (int)nwritten,
4648 conn->num_files_open));
4650 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4651 reply_doserror(req, ERRHRD, ERRdiskfull);
4655 if(!NT_STATUS_IS_OK(close_status)) {
4656 reply_nterror(req, close_status);
4660 reply_outbuf(req, 1, 0);
4662 SSVAL(req->outbuf,smb_vwv0,nwritten);
4666 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4669 END_PROFILE(SMBwriteclose);
4674 #define DBGC_CLASS DBGC_LOCKING
4676 /****************************************************************************
4678 ****************************************************************************/
4680 void reply_lock(struct smb_request *req)
4682 connection_struct *conn = req->conn;
4683 uint64_t count,offset;
4686 struct byte_range_lock *br_lck = NULL;
4688 START_PROFILE(SMBlock);
4691 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4692 END_PROFILE(SMBlock);
4696 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4698 if (!check_fsp(conn, req, fsp)) {
4699 END_PROFILE(SMBlock);
4703 count = (uint64_t)IVAL(req->vwv+1, 0);
4704 offset = (uint64_t)IVAL(req->vwv+3, 0);
4706 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4707 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4709 br_lck = do_lock(smbd_messaging_context(),
4716 False, /* Non-blocking lock. */
4721 TALLOC_FREE(br_lck);
4723 if (NT_STATUS_V(status)) {
4724 reply_nterror(req, status);
4725 END_PROFILE(SMBlock);
4729 reply_outbuf(req, 0, 0);
4731 END_PROFILE(SMBlock);
4735 /****************************************************************************
4737 ****************************************************************************/
4739 void reply_unlock(struct smb_request *req)
4741 connection_struct *conn = req->conn;
4742 uint64_t count,offset;
4746 START_PROFILE(SMBunlock);
4749 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4750 END_PROFILE(SMBunlock);
4754 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4756 if (!check_fsp(conn, req, fsp)) {
4757 END_PROFILE(SMBunlock);
4761 count = (uint64_t)IVAL(req->vwv+1, 0);
4762 offset = (uint64_t)IVAL(req->vwv+3, 0);
4764 status = do_unlock(smbd_messaging_context(),
4771 if (NT_STATUS_V(status)) {
4772 reply_nterror(req, status);
4773 END_PROFILE(SMBunlock);
4777 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4778 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4780 reply_outbuf(req, 0, 0);
4782 END_PROFILE(SMBunlock);
4787 #define DBGC_CLASS DBGC_ALL
4789 /****************************************************************************
4791 conn POINTER CAN BE NULL HERE !
4792 ****************************************************************************/
4794 void reply_tdis(struct smb_request *req)
4796 connection_struct *conn = req->conn;
4797 START_PROFILE(SMBtdis);
4800 DEBUG(4,("Invalid connection in tdis\n"));
4801 reply_doserror(req, ERRSRV, ERRinvnid);
4802 END_PROFILE(SMBtdis);
4808 close_cnum(conn,req->vuid);
4811 reply_outbuf(req, 0, 0);
4812 END_PROFILE(SMBtdis);
4816 /****************************************************************************
4818 conn POINTER CAN BE NULL HERE !
4819 ****************************************************************************/
4821 void reply_echo(struct smb_request *req)
4823 connection_struct *conn = req->conn;
4824 struct smb_perfcount_data local_pcd;
4825 struct smb_perfcount_data *cur_pcd;
4829 START_PROFILE(SMBecho);
4831 smb_init_perfcount_data(&local_pcd);
4834 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4835 END_PROFILE(SMBecho);
4839 smb_reverb = SVAL(req->vwv+0, 0);
4841 reply_outbuf(req, 1, req->buflen);
4843 /* copy any incoming data back out */
4844 if (req->buflen > 0) {
4845 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4848 if (smb_reverb > 100) {
4849 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4853 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4855 /* this makes sure we catch the request pcd */
4856 if (seq_num == smb_reverb) {
4857 cur_pcd = &req->pcd;
4859 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4860 cur_pcd = &local_pcd;
4863 SSVAL(req->outbuf,smb_vwv0,seq_num);
4865 show_msg((char *)req->outbuf);
4866 if (!srv_send_smb(smbd_server_fd(),
4867 (char *)req->outbuf,
4868 true, req->seqnum+1,
4869 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4871 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4874 DEBUG(3,("echo %d times\n", smb_reverb));
4876 TALLOC_FREE(req->outbuf);
4878 END_PROFILE(SMBecho);
4882 /****************************************************************************
4883 Reply to a printopen.
4884 ****************************************************************************/
4886 void reply_printopen(struct smb_request *req)
4888 connection_struct *conn = req->conn;
4890 SMB_STRUCT_STAT sbuf;
4893 START_PROFILE(SMBsplopen);
4896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4897 END_PROFILE(SMBsplopen);
4901 if (!CAN_PRINT(conn)) {
4902 reply_doserror(req, ERRDOS, ERRnoaccess);
4903 END_PROFILE(SMBsplopen);
4907 status = file_new(req, conn, &fsp);
4908 if(!NT_STATUS_IS_OK(status)) {
4909 reply_nterror(req, status);
4910 END_PROFILE(SMBsplopen);
4914 /* Open for exclusive use, write only. */
4915 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4917 if (!NT_STATUS_IS_OK(status)) {
4918 reply_nterror(req, status);
4919 END_PROFILE(SMBsplopen);
4923 reply_outbuf(req, 1, 0);
4924 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4926 DEBUG(3,("openprint fd=%d fnum=%d\n",
4927 fsp->fh->fd, fsp->fnum));
4929 END_PROFILE(SMBsplopen);
4933 /****************************************************************************
4934 Reply to a printclose.
4935 ****************************************************************************/
4937 void reply_printclose(struct smb_request *req)
4939 connection_struct *conn = req->conn;
4943 START_PROFILE(SMBsplclose);
4946 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4947 END_PROFILE(SMBsplclose);
4951 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4953 if (!check_fsp(conn, req, fsp)) {
4954 END_PROFILE(SMBsplclose);
4958 if (!CAN_PRINT(conn)) {
4959 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4960 END_PROFILE(SMBsplclose);
4964 DEBUG(3,("printclose fd=%d fnum=%d\n",
4965 fsp->fh->fd,fsp->fnum));
4967 status = close_file(req, fsp, NORMAL_CLOSE);
4969 if(!NT_STATUS_IS_OK(status)) {
4970 reply_nterror(req, status);
4971 END_PROFILE(SMBsplclose);
4975 reply_outbuf(req, 0, 0);
4977 END_PROFILE(SMBsplclose);
4981 /****************************************************************************
4982 Reply to a printqueue.
4983 ****************************************************************************/
4985 void reply_printqueue(struct smb_request *req)
4987 connection_struct *conn = req->conn;
4991 START_PROFILE(SMBsplretq);
4994 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4995 END_PROFILE(SMBsplretq);
4999 max_count = SVAL(req->vwv+0, 0);
5000 start_index = SVAL(req->vwv+1, 0);
5002 /* we used to allow the client to get the cnum wrong, but that
5003 is really quite gross and only worked when there was only
5004 one printer - I think we should now only accept it if they
5005 get it right (tridge) */
5006 if (!CAN_PRINT(conn)) {
5007 reply_doserror(req, ERRDOS, ERRnoaccess);
5008 END_PROFILE(SMBsplretq);
5012 reply_outbuf(req, 2, 3);
5013 SSVAL(req->outbuf,smb_vwv0,0);
5014 SSVAL(req->outbuf,smb_vwv1,0);
5015 SCVAL(smb_buf(req->outbuf),0,1);
5016 SSVAL(smb_buf(req->outbuf),1,0);
5018 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5019 start_index, max_count));
5022 print_queue_struct *queue = NULL;
5023 print_status_struct status;
5024 int count = print_queue_status(SNUM(conn), &queue, &status);
5025 int num_to_get = ABS(max_count);
5026 int first = (max_count>0?start_index:start_index+max_count+1);
5032 num_to_get = MIN(num_to_get,count-first);
5035 for (i=first;i<first+num_to_get;i++) {
5039 srv_put_dos_date2(p,0,queue[i].time);
5040 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5041 SSVAL(p,5, queue[i].job);
5042 SIVAL(p,7,queue[i].size);
5044 srvstr_push(blob, req->flags2, p+12,
5045 queue[i].fs_user, 16, STR_ASCII);
5047 if (message_push_blob(
5050 blob, sizeof(blob))) == -1) {
5051 reply_nterror(req, NT_STATUS_NO_MEMORY);
5052 END_PROFILE(SMBsplretq);
5058 SSVAL(req->outbuf,smb_vwv0,count);
5059 SSVAL(req->outbuf,smb_vwv1,
5060 (max_count>0?first+count:first-1));
5061 SCVAL(smb_buf(req->outbuf),0,1);
5062 SSVAL(smb_buf(req->outbuf),1,28*count);
5067 DEBUG(3,("%d entries returned in queue\n",count));
5070 END_PROFILE(SMBsplretq);
5074 /****************************************************************************
5075 Reply to a printwrite.
5076 ****************************************************************************/
5078 void reply_printwrite(struct smb_request *req)
5080 connection_struct *conn = req->conn;
5085 START_PROFILE(SMBsplwr);
5088 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5089 END_PROFILE(SMBsplwr);
5093 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5095 if (!check_fsp(conn, req, fsp)) {
5096 END_PROFILE(SMBsplwr);
5100 if (!CAN_PRINT(conn)) {
5101 reply_doserror(req, ERRDOS, ERRnoaccess);
5102 END_PROFILE(SMBsplwr);
5106 if (!CHECK_WRITE(fsp)) {
5107 reply_doserror(req, ERRDOS, ERRbadaccess);
5108 END_PROFILE(SMBsplwr);
5112 numtowrite = SVAL(req->buf, 1);
5114 if (req->buflen < numtowrite + 3) {
5115 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5116 END_PROFILE(SMBsplwr);
5120 data = (const char *)req->buf + 3;
5122 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5123 reply_unixerror(req, ERRHRD, ERRdiskfull);
5124 END_PROFILE(SMBsplwr);
5128 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5130 END_PROFILE(SMBsplwr);
5134 /****************************************************************************
5136 ****************************************************************************/
5138 void reply_mkdir(struct smb_request *req)
5140 connection_struct *conn = req->conn;
5141 char *directory = NULL;
5143 SMB_STRUCT_STAT sbuf;
5144 TALLOC_CTX *ctx = talloc_tos();
5146 START_PROFILE(SMBmkdir);
5148 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5149 STR_TERMINATE, &status);
5150 if (!NT_STATUS_IS_OK(status)) {
5151 reply_nterror(req, status);
5152 END_PROFILE(SMBmkdir);
5156 status = resolve_dfspath(ctx, conn,
5157 req->flags2 & FLAGS2_DFS_PATHNAMES,
5160 if (!NT_STATUS_IS_OK(status)) {
5161 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5162 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5163 ERRSRV, ERRbadpath);
5164 END_PROFILE(SMBmkdir);
5167 reply_nterror(req, status);
5168 END_PROFILE(SMBmkdir);
5172 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
5173 if (!NT_STATUS_IS_OK(status)) {
5174 reply_nterror(req, status);
5175 END_PROFILE(SMBmkdir);
5179 status = check_name(conn, directory);
5180 if (!NT_STATUS_IS_OK(status)) {
5181 reply_nterror(req, status);
5182 END_PROFILE(SMBmkdir);
5186 status = create_directory(conn, req, directory);
5188 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5190 if (!NT_STATUS_IS_OK(status)) {
5192 if (!use_nt_status()
5193 && NT_STATUS_EQUAL(status,
5194 NT_STATUS_OBJECT_NAME_COLLISION)) {
5196 * Yes, in the DOS error code case we get a
5197 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5198 * samba4 torture test.
5200 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5203 reply_nterror(req, status);
5204 END_PROFILE(SMBmkdir);
5208 reply_outbuf(req, 0, 0);
5210 DEBUG( 3, ( "mkdir %s\n", directory ) );
5212 END_PROFILE(SMBmkdir);
5216 /****************************************************************************
5217 Static function used by reply_rmdir to delete an entire directory
5218 tree recursively. Return True on ok, False on fail.
5219 ****************************************************************************/
5221 static bool recursive_rmdir(TALLOC_CTX *ctx,
5222 connection_struct *conn,
5225 const char *dname = NULL;
5229 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5235 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5236 char *fullname = NULL;
5238 if (ISDOT(dname) || ISDOTDOT(dname)) {
5242 if (!is_visible_file(conn, directory, dname, &st, False)) {
5246 /* Construct the full name. */
5247 fullname = talloc_asprintf(ctx,
5257 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5262 if(st.st_mode & S_IFDIR) {
5263 if(!recursive_rmdir(ctx, conn, fullname)) {
5267 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5271 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5275 TALLOC_FREE(fullname);
5277 TALLOC_FREE(dir_hnd);
5281 /****************************************************************************
5282 The internals of the rmdir code - called elsewhere.
5283 ****************************************************************************/
5285 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5286 connection_struct *conn,
5287 const char *directory)
5292 /* Might be a symlink. */
5293 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5294 return map_nt_error_from_unix(errno);
5297 if (S_ISLNK(st.st_mode)) {
5298 /* Is what it points to a directory ? */
5299 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5300 return map_nt_error_from_unix(errno);
5302 if (!(S_ISDIR(st.st_mode))) {
5303 return NT_STATUS_NOT_A_DIRECTORY;
5305 ret = SMB_VFS_UNLINK(conn,directory);
5307 ret = SMB_VFS_RMDIR(conn,directory);
5310 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5311 FILE_NOTIFY_CHANGE_DIR_NAME,
5313 return NT_STATUS_OK;
5316 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5318 * Check to see if the only thing in this directory are
5319 * vetoed files/directories. If so then delete them and
5320 * retry. If we fail to delete any of them (and we *don't*
5321 * do a recursive delete) then fail the rmdir.
5325 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5326 directory, NULL, 0);
5328 if(dir_hnd == NULL) {
5333 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5334 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5336 if (!is_visible_file(conn, directory, dname, &st, False))
5338 if(!IS_VETO_PATH(conn, dname)) {
5339 TALLOC_FREE(dir_hnd);
5345 /* We only have veto files/directories.
5346 * Are we allowed to delete them ? */
5348 if(!lp_recursive_veto_delete(SNUM(conn))) {
5349 TALLOC_FREE(dir_hnd);
5354 /* Do a recursive delete. */
5355 RewindDir(dir_hnd,&dirpos);
5356 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5357 char *fullname = NULL;
5359 if (ISDOT(dname) || ISDOTDOT(dname)) {
5362 if (!is_visible_file(conn, directory, dname, &st, False)) {
5366 fullname = talloc_asprintf(ctx,
5376 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5379 if(st.st_mode & S_IFDIR) {
5380 if(!recursive_rmdir(ctx, conn, fullname)) {
5383 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5386 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5389 TALLOC_FREE(fullname);
5391 TALLOC_FREE(dir_hnd);
5392 /* Retry the rmdir */
5393 ret = SMB_VFS_RMDIR(conn,directory);
5399 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5400 "%s\n", directory,strerror(errno)));
5401 return map_nt_error_from_unix(errno);
5404 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5405 FILE_NOTIFY_CHANGE_DIR_NAME,
5408 return NT_STATUS_OK;
5411 /****************************************************************************
5413 ****************************************************************************/
5415 void reply_rmdir(struct smb_request *req)
5417 connection_struct *conn = req->conn;
5418 char *directory = NULL;
5419 SMB_STRUCT_STAT sbuf;
5421 TALLOC_CTX *ctx = talloc_tos();
5423 START_PROFILE(SMBrmdir);
5425 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5426 STR_TERMINATE, &status);
5427 if (!NT_STATUS_IS_OK(status)) {
5428 reply_nterror(req, status);
5429 END_PROFILE(SMBrmdir);
5433 status = resolve_dfspath(ctx, conn,
5434 req->flags2 & FLAGS2_DFS_PATHNAMES,
5437 if (!NT_STATUS_IS_OK(status)) {
5438 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5439 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5440 ERRSRV, ERRbadpath);
5441 END_PROFILE(SMBrmdir);
5444 reply_nterror(req, status);
5445 END_PROFILE(SMBrmdir);
5449 status = unix_convert(ctx, conn, directory, False, &directory,
5451 if (!NT_STATUS_IS_OK(status)) {
5452 reply_nterror(req, status);
5453 END_PROFILE(SMBrmdir);
5457 status = check_name(conn, directory);
5458 if (!NT_STATUS_IS_OK(status)) {
5459 reply_nterror(req, status);
5460 END_PROFILE(SMBrmdir);
5464 dptr_closepath(directory, req->smbpid);
5465 status = rmdir_internals(ctx, conn, directory);
5466 if (!NT_STATUS_IS_OK(status)) {
5467 reply_nterror(req, status);
5468 END_PROFILE(SMBrmdir);
5472 reply_outbuf(req, 0, 0);
5474 DEBUG( 3, ( "rmdir %s\n", directory ) );
5476 END_PROFILE(SMBrmdir);
5480 /*******************************************************************
5481 Resolve wildcards in a filename rename.
5482 ********************************************************************/
5484 static bool resolve_wildcards(TALLOC_CTX *ctx,
5489 char *name2_copy = NULL;
5494 char *p,*p2, *pname1, *pname2;
5496 name2_copy = talloc_strdup(ctx, name2);
5501 pname1 = strrchr_m(name1,'/');
5502 pname2 = strrchr_m(name2_copy,'/');
5504 if (!pname1 || !pname2) {
5508 /* Truncate the copy of name2 at the last '/' */
5511 /* Now go past the '/' */
5515 root1 = talloc_strdup(ctx, pname1);
5516 root2 = talloc_strdup(ctx, pname2);
5518 if (!root1 || !root2) {
5522 p = strrchr_m(root1,'.');
5525 ext1 = talloc_strdup(ctx, p+1);
5527 ext1 = talloc_strdup(ctx, "");
5529 p = strrchr_m(root2,'.');
5532 ext2 = talloc_strdup(ctx, p+1);
5534 ext2 = talloc_strdup(ctx, "");
5537 if (!ext1 || !ext2) {
5545 /* Hmmm. Should this be mb-aware ? */
5548 } else if (*p2 == '*') {
5550 root2 = talloc_asprintf(ctx, "%s%s",
5569 /* Hmmm. Should this be mb-aware ? */
5572 } else if (*p2 == '*') {
5574 ext2 = talloc_asprintf(ctx, "%s%s",
5590 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5595 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5607 /****************************************************************************
5608 Ensure open files have their names updated. Updated to notify other smbd's
5610 ****************************************************************************/
5612 static void rename_open_files(connection_struct *conn,
5613 struct share_mode_lock *lck,
5614 const char *newname)
5617 bool did_rename = False;
5619 for(fsp = file_find_di_first(lck->id); fsp;
5620 fsp = file_find_di_next(fsp)) {
5621 /* fsp_name is a relative path under the fsp. To change this for other
5622 sharepaths we need to manipulate relative paths. */
5623 /* TODO - create the absolute path and manipulate the newname
5624 relative to the sharepath. */
5625 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5628 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5629 fsp->fnum, file_id_string_tos(&fsp->file_id),
5630 fsp->fsp_name, newname ));
5631 string_set(&fsp->fsp_name, newname);
5636 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5637 file_id_string_tos(&lck->id), newname ));
5640 /* Send messages to all smbd's (not ourself) that the name has changed. */
5641 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5645 /****************************************************************************
5646 We need to check if the source path is a parent directory of the destination
5647 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5648 refuse the rename with a sharing violation. Under UNIX the above call can
5649 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5650 probably need to check that the client is a Windows one before disallowing
5651 this as a UNIX client (one with UNIX extensions) can know the source is a
5652 symlink and make this decision intelligently. Found by an excellent bug
5653 report from <AndyLiebman@aol.com>.
5654 ****************************************************************************/
5656 static bool rename_path_prefix_equal(const char *src, const char *dest)
5658 const char *psrc = src;
5659 const char *pdst = dest;
5662 if (psrc[0] == '.' && psrc[1] == '/') {
5665 if (pdst[0] == '.' && pdst[1] == '/') {
5668 if ((slen = strlen(psrc)) > strlen(pdst)) {
5671 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5675 * Do the notify calls from a rename
5678 static void notify_rename(connection_struct *conn, bool is_dir,
5679 const char *oldpath, const char *newpath)
5681 char *olddir, *newdir;
5682 const char *oldname, *newname;
5685 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5686 : FILE_NOTIFY_CHANGE_FILE_NAME;
5688 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5689 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5690 TALLOC_FREE(olddir);
5694 if (strcmp(olddir, newdir) == 0) {
5695 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5696 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5699 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5700 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5702 TALLOC_FREE(olddir);
5703 TALLOC_FREE(newdir);
5705 /* this is a strange one. w2k3 gives an additional event for
5706 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5707 files, but not directories */
5709 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5710 FILE_NOTIFY_CHANGE_ATTRIBUTES
5711 |FILE_NOTIFY_CHANGE_CREATION,
5716 /****************************************************************************
5717 Rename an open file - given an fsp.
5718 ****************************************************************************/
5720 NTSTATUS rename_internals_fsp(connection_struct *conn,
5723 const char *newname_last_component,
5725 bool replace_if_exists)
5727 TALLOC_CTX *ctx = talloc_tos();
5728 SMB_STRUCT_STAT sbuf, sbuf1;
5729 NTSTATUS status = NT_STATUS_OK;
5730 struct share_mode_lock *lck = NULL;
5731 bool dst_exists, old_is_stream, new_is_stream;
5735 status = check_name(conn, newname);
5736 if (!NT_STATUS_IS_OK(status)) {
5740 /* Ensure newname contains a '/' */
5741 if(strrchr_m(newname,'/') == 0) {
5742 newname = talloc_asprintf(ctx,
5746 return NT_STATUS_NO_MEMORY;
5751 * Check for special case with case preserving and not
5752 * case sensitive. If the old last component differs from the original
5753 * last component only by case, then we should allow
5754 * the rename (user is trying to change the case of the
5758 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5759 strequal(newname, fsp->fsp_name)) {
5761 char *newname_modified_last_component = NULL;
5764 * Get the last component of the modified name.
5765 * Note that we guarantee that newname contains a '/'
5768 p = strrchr_m(newname,'/');
5769 newname_modified_last_component = talloc_strdup(ctx,
5771 if (!newname_modified_last_component) {
5772 return NT_STATUS_NO_MEMORY;
5775 if(strcsequal(newname_modified_last_component,
5776 newname_last_component) == False) {
5778 * Replace the modified last component with
5781 *p = '\0'; /* Truncate at the '/' */
5782 newname = talloc_asprintf(ctx,
5785 newname_last_component);
5790 * If the src and dest names are identical - including case,
5791 * don't do the rename, just return success.
5794 if (strcsequal(fsp->fsp_name, newname)) {
5795 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5797 return NT_STATUS_OK;
5800 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5801 new_is_stream = is_ntfs_stream_name(newname);
5803 /* Return the correct error code if both names aren't streams. */
5804 if (!old_is_stream && new_is_stream) {
5805 return NT_STATUS_OBJECT_NAME_INVALID;
5808 if (old_is_stream && !new_is_stream) {
5809 return NT_STATUS_INVALID_PARAMETER;
5813 * Have vfs_object_exist also fill sbuf1
5815 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5817 if(!replace_if_exists && dst_exists) {
5818 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5819 fsp->fsp_name,newname));
5820 return NT_STATUS_OBJECT_NAME_COLLISION;
5824 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5825 files_struct *dst_fsp = file_find_di_first(fileid);
5826 /* The file can be open when renaming a stream */
5827 if (dst_fsp && !new_is_stream) {
5828 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5829 return NT_STATUS_ACCESS_DENIED;
5833 /* Ensure we have a valid stat struct for the source. */
5834 if (fsp->fh->fd != -1) {
5835 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5836 return map_nt_error_from_unix(errno);
5840 if (fsp->posix_open) {
5841 ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
5843 ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
5846 return map_nt_error_from_unix(errno);
5850 status = can_rename(conn, fsp, attrs, &sbuf);
5852 if (!NT_STATUS_IS_OK(status)) {
5853 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5854 nt_errstr(status), fsp->fsp_name,newname));
5855 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5856 status = NT_STATUS_ACCESS_DENIED;
5860 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5861 return NT_STATUS_ACCESS_DENIED;
5864 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5868 * We have the file open ourselves, so not being able to get the
5869 * corresponding share mode lock is a fatal error.
5872 SMB_ASSERT(lck != NULL);
5874 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5875 uint32 create_options = fsp->fh->private_options;
5877 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5878 fsp->fsp_name,newname));
5880 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5882 rename_open_files(conn, lck, newname);
5885 * A rename acts as a new file create w.r.t. allowing an initial delete
5886 * on close, probably because in Windows there is a new handle to the
5887 * new file. If initial delete on close was requested but not
5888 * originally set, we need to set it here. This is probably not 100% correct,
5889 * but will work for the CIFSFS client which in non-posix mode
5890 * depends on these semantics. JRA.
5893 if (create_options & FILE_DELETE_ON_CLOSE) {
5894 status = can_set_delete_on_close(fsp, True, 0);
5896 if (NT_STATUS_IS_OK(status)) {
5897 /* Note that here we set the *inital* delete on close flag,
5898 * not the regular one. The magic gets handled in close. */
5899 fsp->initial_delete_on_close = True;
5903 return NT_STATUS_OK;
5908 if (errno == ENOTDIR || errno == EISDIR) {
5909 status = NT_STATUS_OBJECT_NAME_COLLISION;
5911 status = map_nt_error_from_unix(errno);
5914 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5915 nt_errstr(status), fsp->fsp_name,newname));
5920 /****************************************************************************
5921 The guts of the rename command, split out so it may be called by the NT SMB
5923 ****************************************************************************/
5925 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5926 connection_struct *conn,
5927 struct smb_request *req,
5928 const char *name_in,
5929 const char *newname_in,
5931 bool replace_if_exists,
5934 uint32_t access_mask)
5936 char *directory = NULL;
5938 char *last_component_src = NULL;
5939 char *last_component_dest = NULL;
5941 char *newname = NULL;
5944 NTSTATUS status = NT_STATUS_OK;
5945 SMB_STRUCT_STAT sbuf1, sbuf2;
5946 struct smb_Dir *dir_hnd = NULL;
5949 int create_options = 0;
5950 bool posix_pathnames = lp_posix_pathnames();
5955 status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5956 &last_component_src, &sbuf1);
5957 if (!NT_STATUS_IS_OK(status)) {
5961 status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5962 &last_component_dest, &sbuf2);
5963 if (!NT_STATUS_IS_OK(status)) {
5968 * Split the old name into directory and last component
5969 * strings. Note that unix_convert may have stripped off a
5970 * leading ./ from both name and newname if the rename is
5971 * at the root of the share. We need to make sure either both
5972 * name and newname contain a / character or neither of them do
5973 * as this is checked in resolve_wildcards().
5976 p = strrchr_m(name,'/');
5978 directory = talloc_strdup(ctx, ".");
5980 return NT_STATUS_NO_MEMORY;
5985 directory = talloc_strdup(ctx, name);
5987 return NT_STATUS_NO_MEMORY;
5990 *p = '/'; /* Replace needed for exceptional test below. */
5994 * We should only check the mangled cache
5995 * here if unix_convert failed. This means
5996 * that the path in 'mask' doesn't exist
5997 * on the file system and so we need to look
5998 * for a possible mangle. This patch from
5999 * Tine Smukavec <valentin.smukavec@hermes.si>.
6002 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6003 char *new_mask = NULL;
6004 mangle_lookup_name_from_8_3(ctx,
6013 if (!src_has_wild) {
6017 * No wildcards - just process the one file.
6019 bool is_short_name = mangle_is_8_3(name, True, conn->params);
6021 /* Add a terminating '/' to the directory name. */
6022 directory = talloc_asprintf_append(directory,
6026 return NT_STATUS_NO_MEMORY;
6029 /* Ensure newname contains a '/' also */
6030 if(strrchr_m(newname,'/') == 0) {
6031 newname = talloc_asprintf(ctx,
6035 return NT_STATUS_NO_MEMORY;
6039 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6040 "case_preserve = %d, short case preserve = %d, "
6041 "directory = %s, newname = %s, "
6042 "last_component_dest = %s, is_8_3 = %d\n",
6043 conn->case_sensitive, conn->case_preserve,
6044 conn->short_case_preserve, directory,
6045 newname, last_component_dest, is_short_name));
6047 /* The dest name still may have wildcards. */
6048 if (dest_has_wild) {
6049 char *mod_newname = NULL;
6050 if (!resolve_wildcards(ctx,
6051 directory,newname,&mod_newname)) {
6052 DEBUG(6, ("rename_internals: resolve_wildcards "
6056 return NT_STATUS_NO_MEMORY;
6058 newname = mod_newname;
6062 if (posix_pathnames) {
6063 SMB_VFS_LSTAT(conn, directory, &sbuf1);
6065 SMB_VFS_STAT(conn, directory, &sbuf1);
6068 if (S_ISDIR(sbuf1.st_mode)) {
6069 create_options |= FILE_DIRECTORY_FILE;
6072 status = SMB_VFS_CREATE_FILE(
6075 0, /* root_dir_fid */
6076 directory, /* fname */
6077 0, /* create_file_flags */
6078 access_mask, /* access_mask */
6079 (FILE_SHARE_READ | /* share_access */
6081 FILE_OPEN, /* create_disposition*/
6082 create_options, /* create_options */
6083 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6084 0, /* oplock_request */
6085 0, /* allocation_size */
6090 &sbuf1); /* psbuf */
6092 if (!NT_STATUS_IS_OK(status)) {
6093 DEBUG(3, ("Could not open rename source %s: %s\n",
6094 directory, nt_errstr(status)));
6098 status = rename_internals_fsp(conn, fsp, newname,
6099 last_component_dest,
6100 attrs, replace_if_exists);
6102 close_file(req, fsp, NORMAL_CLOSE);
6104 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6105 nt_errstr(status), directory,newname));
6111 * Wildcards - process each file that matches.
6113 if (strequal(mask,"????????.???")) {
6118 status = check_name(conn, directory);
6119 if (!NT_STATUS_IS_OK(status)) {
6123 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
6124 if (dir_hnd == NULL) {
6125 return map_nt_error_from_unix(errno);
6128 status = NT_STATUS_NO_SUCH_FILE;
6130 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6131 * - gentest fix. JRA
6134 while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
6135 files_struct *fsp = NULL;
6137 char *destname = NULL;
6138 bool sysdir_entry = False;
6140 /* Quick check for "." and ".." */
6141 if (ISDOT(dname) || ISDOTDOT(dname)) {
6143 sysdir_entry = True;
6149 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6153 if(!mask_match(dname, mask, conn->case_sensitive)) {
6158 status = NT_STATUS_OBJECT_NAME_INVALID;
6162 fname = talloc_asprintf(ctx,
6167 return NT_STATUS_NO_MEMORY;
6170 if (!resolve_wildcards(ctx,
6171 fname,newname,&destname)) {
6172 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6178 return NT_STATUS_NO_MEMORY;
6182 if (posix_pathnames) {
6183 SMB_VFS_LSTAT(conn, fname, &sbuf1);
6185 SMB_VFS_STAT(conn, fname, &sbuf1);
6190 if (S_ISDIR(sbuf1.st_mode)) {
6191 create_options |= FILE_DIRECTORY_FILE;
6194 status = SMB_VFS_CREATE_FILE(
6197 0, /* root_dir_fid */
6199 0, /* create_file_flags */
6200 access_mask, /* access_mask */
6201 (FILE_SHARE_READ | /* share_access */
6203 FILE_OPEN, /* create_disposition*/
6204 create_options, /* create_options */
6205 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6206 0, /* oplock_request */
6207 0, /* allocation_size */
6212 &sbuf1); /* psbuf */
6214 if (!NT_STATUS_IS_OK(status)) {
6215 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6216 "returned %s rename %s -> %s\n",
6217 nt_errstr(status), directory, newname));
6221 status = rename_internals_fsp(conn, fsp, destname, dname,
6222 attrs, replace_if_exists);
6224 close_file(req, fsp, NORMAL_CLOSE);
6226 if (!NT_STATUS_IS_OK(status)) {
6227 DEBUG(3, ("rename_internals_fsp returned %s for "
6228 "rename %s -> %s\n", nt_errstr(status),
6229 directory, newname));
6235 DEBUG(3,("rename_internals: doing rename on %s -> "
6236 "%s\n",fname,destname));
6239 TALLOC_FREE(destname);
6241 TALLOC_FREE(dir_hnd);
6243 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6244 status = map_nt_error_from_unix(errno);
6250 /****************************************************************************
6252 ****************************************************************************/
6254 void reply_mv(struct smb_request *req)
6256 connection_struct *conn = req->conn;
6258 char *newname = NULL;
6262 bool src_has_wcard = False;
6263 bool dest_has_wcard = False;
6264 TALLOC_CTX *ctx = talloc_tos();
6266 START_PROFILE(SMBmv);
6269 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6274 attrs = SVAL(req->vwv+0, 0);
6276 p = (const char *)req->buf + 1;
6277 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6278 &status, &src_has_wcard);
6279 if (!NT_STATUS_IS_OK(status)) {
6280 reply_nterror(req, status);
6285 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6286 &status, &dest_has_wcard);
6287 if (!NT_STATUS_IS_OK(status)) {
6288 reply_nterror(req, status);
6293 status = resolve_dfspath_wcard(ctx, conn,
6294 req->flags2 & FLAGS2_DFS_PATHNAMES,
6298 if (!NT_STATUS_IS_OK(status)) {
6299 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6300 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6301 ERRSRV, ERRbadpath);
6305 reply_nterror(req, status);
6310 status = resolve_dfspath_wcard(ctx, conn,
6311 req->flags2 & FLAGS2_DFS_PATHNAMES,
6315 if (!NT_STATUS_IS_OK(status)) {
6316 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6317 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6318 ERRSRV, ERRbadpath);
6322 reply_nterror(req, status);
6327 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6329 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6330 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6331 if (!NT_STATUS_IS_OK(status)) {
6332 if (open_was_deferred(req->mid)) {
6333 /* We have re-scheduled this call. */
6337 reply_nterror(req, status);
6342 reply_outbuf(req, 0, 0);
6348 /*******************************************************************
6349 Copy a file as part of a reply_copy.
6350 ******************************************************************/
6353 * TODO: check error codes on all callers
6356 NTSTATUS copy_file(TALLOC_CTX *ctx,
6357 connection_struct *conn,
6362 bool target_is_directory)
6364 SMB_STRUCT_STAT src_sbuf, sbuf2;
6366 files_struct *fsp1,*fsp2;
6369 uint32 new_create_disposition;
6372 dest = talloc_strdup(ctx, dest1);
6374 return NT_STATUS_NO_MEMORY;
6376 if (target_is_directory) {
6377 const char *p = strrchr_m(src,'/');
6383 dest = talloc_asprintf_append(dest,
6387 return NT_STATUS_NO_MEMORY;
6391 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6393 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6396 if (!target_is_directory && count) {
6397 new_create_disposition = FILE_OPEN;
6399 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6400 NULL, NULL, &new_create_disposition, NULL)) {
6402 return NT_STATUS_INVALID_PARAMETER;
6406 status = SMB_VFS_CREATE_FILE(
6409 0, /* root_dir_fid */
6411 0, /* create_file_flags */
6412 FILE_GENERIC_READ, /* access_mask */
6413 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6414 FILE_OPEN, /* create_disposition*/
6415 0, /* create_options */
6416 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6417 INTERNAL_OPEN_ONLY, /* oplock_request */
6418 0, /* allocation_size */
6423 &src_sbuf); /* psbuf */
6425 if (!NT_STATUS_IS_OK(status)) {
6430 dosattrs = dos_mode(conn, src, &src_sbuf);
6431 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6432 ZERO_STRUCTP(&sbuf2);
6435 status = SMB_VFS_CREATE_FILE(
6438 0, /* root_dir_fid */
6440 0, /* create_file_flags */
6441 FILE_GENERIC_WRITE, /* access_mask */
6442 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6443 new_create_disposition, /* create_disposition*/
6444 0, /* create_options */
6445 dosattrs, /* file_attributes */
6446 INTERNAL_OPEN_ONLY, /* oplock_request */
6447 0, /* allocation_size */
6452 &sbuf2); /* psbuf */
6456 if (!NT_STATUS_IS_OK(status)) {
6457 close_file(NULL, fsp1, ERROR_CLOSE);
6461 if ((ofun&3) == 1) {
6462 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6463 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6465 * Stop the copy from occurring.
6468 src_sbuf.st_size = 0;
6472 if (src_sbuf.st_size) {
6473 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6476 close_file(NULL, fsp1, NORMAL_CLOSE);
6478 /* Ensure the modtime is set correctly on the destination file. */
6479 set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
6482 * As we are opening fsp1 read-only we only expect
6483 * an error on close on fsp2 if we are out of space.
6484 * Thus we don't look at the error return from the
6487 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6489 if (!NT_STATUS_IS_OK(status)) {
6493 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6494 return NT_STATUS_DISK_FULL;
6497 return NT_STATUS_OK;
6500 /****************************************************************************
6501 Reply to a file copy.
6502 ****************************************************************************/
6504 void reply_copy(struct smb_request *req)
6506 connection_struct *conn = req->conn;
6508 char *newname = NULL;
6509 char *directory = NULL;
6510 const char *mask = NULL;
6511 const char mask_star[] = "*";
6514 int error = ERRnoaccess;
6519 bool target_is_directory=False;
6520 bool source_has_wild = False;
6521 bool dest_has_wild = False;
6522 SMB_STRUCT_STAT sbuf1, sbuf2;
6524 TALLOC_CTX *ctx = talloc_tos();
6526 START_PROFILE(SMBcopy);
6529 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6530 END_PROFILE(SMBcopy);
6534 tid2 = SVAL(req->vwv+0, 0);
6535 ofun = SVAL(req->vwv+1, 0);
6536 flags = SVAL(req->vwv+2, 0);
6538 p = (const char *)req->buf;
6539 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6540 &status, &source_has_wild);
6541 if (!NT_STATUS_IS_OK(status)) {
6542 reply_nterror(req, status);
6543 END_PROFILE(SMBcopy);
6546 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6547 &status, &dest_has_wild);
6548 if (!NT_STATUS_IS_OK(status)) {
6549 reply_nterror(req, status);
6550 END_PROFILE(SMBcopy);
6554 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6556 if (tid2 != conn->cnum) {
6557 /* can't currently handle inter share copies XXXX */
6558 DEBUG(3,("Rejecting inter-share copy\n"));
6559 reply_doserror(req, ERRSRV, ERRinvdevice);
6560 END_PROFILE(SMBcopy);
6564 status = resolve_dfspath_wcard(ctx, conn,
6565 req->flags2 & FLAGS2_DFS_PATHNAMES,
6569 if (!NT_STATUS_IS_OK(status)) {
6570 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6571 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6572 ERRSRV, ERRbadpath);
6573 END_PROFILE(SMBcopy);
6576 reply_nterror(req, status);
6577 END_PROFILE(SMBcopy);
6581 status = resolve_dfspath_wcard(ctx, conn,
6582 req->flags2 & FLAGS2_DFS_PATHNAMES,
6586 if (!NT_STATUS_IS_OK(status)) {
6587 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6588 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6589 ERRSRV, ERRbadpath);
6590 END_PROFILE(SMBcopy);
6593 reply_nterror(req, status);
6594 END_PROFILE(SMBcopy);
6598 status = unix_convert(ctx, conn, name, source_has_wild,
6599 &name, NULL, &sbuf1);
6600 if (!NT_STATUS_IS_OK(status)) {
6601 reply_nterror(req, status);
6602 END_PROFILE(SMBcopy);
6606 status = unix_convert(ctx, conn, newname, dest_has_wild,
6607 &newname, NULL, &sbuf2);
6608 if (!NT_STATUS_IS_OK(status)) {
6609 reply_nterror(req, status);
6610 END_PROFILE(SMBcopy);
6614 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6616 if ((flags&1) && target_is_directory) {
6617 reply_doserror(req, ERRDOS, ERRbadfile);
6618 END_PROFILE(SMBcopy);
6622 if ((flags&2) && !target_is_directory) {
6623 reply_doserror(req, ERRDOS, ERRbadpath);
6624 END_PROFILE(SMBcopy);
6628 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6629 /* wants a tree copy! XXXX */
6630 DEBUG(3,("Rejecting tree copy\n"));
6631 reply_doserror(req, ERRSRV, ERRerror);
6632 END_PROFILE(SMBcopy);
6636 p = strrchr_m(name,'/');
6638 directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
6641 directory = talloc_strdup(ctx, "./");
6646 reply_nterror(req, NT_STATUS_NO_MEMORY);
6647 END_PROFILE(SMBcopy);
6652 * We should only check the mangled cache
6653 * here if unix_convert failed. This means
6654 * that the path in 'mask' doesn't exist
6655 * on the file system and so we need to look
6656 * for a possible mangle. This patch from
6657 * Tine Smukavec <valentin.smukavec@hermes.si>.
6660 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6661 char *new_mask = NULL;
6662 mangle_lookup_name_from_8_3(ctx,
6671 if (!source_has_wild) {
6672 directory = talloc_asprintf_append(directory,
6675 if (dest_has_wild) {
6676 char *mod_newname = NULL;
6677 if (!resolve_wildcards(ctx,
6678 directory,newname,&mod_newname)) {
6679 reply_nterror(req, NT_STATUS_NO_MEMORY);
6680 END_PROFILE(SMBcopy);
6683 newname = mod_newname;
6686 status = check_name(conn, directory);
6687 if (!NT_STATUS_IS_OK(status)) {
6688 reply_nterror(req, status);
6689 END_PROFILE(SMBcopy);
6693 status = check_name(conn, newname);
6694 if (!NT_STATUS_IS_OK(status)) {
6695 reply_nterror(req, status);
6696 END_PROFILE(SMBcopy);
6700 status = copy_file(ctx,conn,directory,newname,ofun,
6701 count,target_is_directory);
6703 if(!NT_STATUS_IS_OK(status)) {
6704 reply_nterror(req, status);
6705 END_PROFILE(SMBcopy);
6711 struct smb_Dir *dir_hnd = NULL;
6712 const char *dname = NULL;
6715 if (strequal(mask,"????????.???")) {
6719 status = check_name(conn, directory);
6720 if (!NT_STATUS_IS_OK(status)) {
6721 reply_nterror(req, status);
6722 END_PROFILE(SMBcopy);
6726 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6727 if (dir_hnd == NULL) {
6728 status = map_nt_error_from_unix(errno);
6729 reply_nterror(req, status);
6730 END_PROFILE(SMBcopy);
6736 while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
6737 char *destname = NULL;
6740 if (ISDOT(dname) || ISDOTDOT(dname)) {
6744 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6748 if(!mask_match(dname, mask, conn->case_sensitive)) {
6752 error = ERRnoaccess;
6753 fname = talloc_asprintf(ctx,
6758 TALLOC_FREE(dir_hnd);
6759 reply_nterror(req, NT_STATUS_NO_MEMORY);
6760 END_PROFILE(SMBcopy);
6764 if (!resolve_wildcards(ctx,
6765 fname,newname,&destname)) {
6769 TALLOC_FREE(dir_hnd);
6770 reply_nterror(req, NT_STATUS_NO_MEMORY);
6771 END_PROFILE(SMBcopy);
6775 status = check_name(conn, fname);
6776 if (!NT_STATUS_IS_OK(status)) {
6777 TALLOC_FREE(dir_hnd);
6778 reply_nterror(req, status);
6779 END_PROFILE(SMBcopy);
6783 status = check_name(conn, destname);
6784 if (!NT_STATUS_IS_OK(status)) {
6785 TALLOC_FREE(dir_hnd);
6786 reply_nterror(req, status);
6787 END_PROFILE(SMBcopy);
6791 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6793 status = copy_file(ctx,conn,fname,destname,ofun,
6794 count,target_is_directory);
6795 if (NT_STATUS_IS_OK(status)) {
6799 TALLOC_FREE(destname);
6801 TALLOC_FREE(dir_hnd);
6806 /* Error on close... */
6808 reply_unixerror(req, ERRHRD, ERRgeneral);
6809 END_PROFILE(SMBcopy);
6813 reply_doserror(req, ERRDOS, error);
6814 END_PROFILE(SMBcopy);
6818 reply_outbuf(req, 1, 0);
6819 SSVAL(req->outbuf,smb_vwv0,count);
6821 END_PROFILE(SMBcopy);
6826 #define DBGC_CLASS DBGC_LOCKING
6828 /****************************************************************************
6829 Get a lock pid, dealing with large count requests.
6830 ****************************************************************************/
6832 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6833 bool large_file_format)
6835 if(!large_file_format)
6836 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6838 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6841 /****************************************************************************
6842 Get a lock count, dealing with large count requests.
6843 ****************************************************************************/
6845 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6846 bool large_file_format)
6850 if(!large_file_format) {
6851 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6854 #if defined(HAVE_LONGLONG)
6855 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6856 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6857 #else /* HAVE_LONGLONG */
6860 * NT4.x seems to be broken in that it sends large file (64 bit)
6861 * lockingX calls even if the CAP_LARGE_FILES was *not*
6862 * negotiated. For boxes without large unsigned ints truncate the
6863 * lock count by dropping the top 32 bits.
6866 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6867 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6868 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6869 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6870 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6873 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6874 #endif /* HAVE_LONGLONG */
6880 #if !defined(HAVE_LONGLONG)
6881 /****************************************************************************
6882 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6883 ****************************************************************************/
6885 static uint32 map_lock_offset(uint32 high, uint32 low)
6889 uint32 highcopy = high;
6892 * Try and find out how many significant bits there are in high.
6895 for(i = 0; highcopy; i++)
6899 * We use 31 bits not 32 here as POSIX
6900 * lock offsets may not be negative.
6903 mask = (~0) << (31 - i);
6906 return 0; /* Fail. */
6912 #endif /* !defined(HAVE_LONGLONG) */
6914 /****************************************************************************
6915 Get a lock offset, dealing with large offset requests.
6916 ****************************************************************************/
6918 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6919 bool large_file_format, bool *err)
6921 uint64_t offset = 0;
6925 if(!large_file_format) {
6926 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6929 #if defined(HAVE_LONGLONG)
6930 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6931 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6932 #else /* HAVE_LONGLONG */
6935 * NT4.x seems to be broken in that it sends large file (64 bit)
6936 * lockingX calls even if the CAP_LARGE_FILES was *not*
6937 * negotiated. For boxes without large unsigned ints mangle the
6938 * lock offset by mapping the top 32 bits onto the lower 32.
6941 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6942 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6943 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6946 if((new_low = map_lock_offset(high, low)) == 0) {
6948 return (uint64_t)-1;
6951 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6952 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6953 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6954 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6957 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6958 #endif /* HAVE_LONGLONG */
6964 /****************************************************************************
6965 Reply to a lockingX request.
6966 ****************************************************************************/
6968 void reply_lockingX(struct smb_request *req)
6970 connection_struct *conn = req->conn;
6972 unsigned char locktype;
6973 unsigned char oplocklevel;
6976 uint64_t count = 0, offset = 0;
6980 const uint8_t *data;
6981 bool large_file_format;
6983 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6985 START_PROFILE(SMBlockingX);
6988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6989 END_PROFILE(SMBlockingX);
6993 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
6994 locktype = CVAL(req->vwv+3, 0);
6995 oplocklevel = CVAL(req->vwv+3, 1);
6996 num_ulocks = SVAL(req->vwv+6, 0);
6997 num_locks = SVAL(req->vwv+7, 0);
6998 lock_timeout = IVAL(req->vwv+4, 0);
6999 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7001 if (!check_fsp(conn, req, fsp)) {
7002 END_PROFILE(SMBlockingX);
7008 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7009 /* we don't support these - and CANCEL_LOCK makes w2k
7010 and XP reboot so I don't really want to be
7011 compatible! (tridge) */
7012 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7013 END_PROFILE(SMBlockingX);
7017 /* Check if this is an oplock break on a file
7018 we have granted an oplock on.
7020 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7021 /* Client can insist on breaking to none. */
7022 bool break_to_none = (oplocklevel == 0);
7025 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7026 "for fnum = %d\n", (unsigned int)oplocklevel,
7030 * Make sure we have granted an exclusive or batch oplock on
7034 if (fsp->oplock_type == 0) {
7036 /* The Samba4 nbench simulator doesn't understand
7037 the difference between break to level2 and break
7038 to none from level2 - it sends oplock break
7039 replies in both cases. Don't keep logging an error
7040 message here - just ignore it. JRA. */
7042 DEBUG(5,("reply_lockingX: Error : oplock break from "
7043 "client for fnum = %d (oplock=%d) and no "
7044 "oplock granted on this file (%s).\n",
7045 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
7047 /* if this is a pure oplock break request then don't
7049 if (num_locks == 0 && num_ulocks == 0) {
7050 END_PROFILE(SMBlockingX);
7053 END_PROFILE(SMBlockingX);
7054 reply_doserror(req, ERRDOS, ERRlock);
7059 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7061 result = remove_oplock(fsp);
7063 result = downgrade_oplock(fsp);
7067 DEBUG(0, ("reply_lockingX: error in removing "
7068 "oplock on file %s\n", fsp->fsp_name));
7069 /* Hmmm. Is this panic justified? */
7070 smb_panic("internal tdb error");
7073 reply_to_oplock_break_requests(fsp);
7075 /* if this is a pure oplock break request then don't send a
7077 if (num_locks == 0 && num_ulocks == 0) {
7078 /* Sanity check - ensure a pure oplock break is not a
7080 if(CVAL(req->vwv+0, 0) != 0xff)
7081 DEBUG(0,("reply_lockingX: Error : pure oplock "
7082 "break is a chained %d request !\n",
7083 (unsigned int)CVAL(req->vwv+0, 0)));
7084 END_PROFILE(SMBlockingX);
7090 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7091 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7092 END_PROFILE(SMBlockingX);
7096 /* Data now points at the beginning of the list
7097 of smb_unlkrng structs */
7098 for(i = 0; i < (int)num_ulocks; i++) {
7099 lock_pid = get_lock_pid( data, i, large_file_format);
7100 count = get_lock_count( data, i, large_file_format);
7101 offset = get_lock_offset( data, i, large_file_format, &err);
7104 * There is no error code marked "stupid client bug".... :-).
7107 END_PROFILE(SMBlockingX);
7108 reply_doserror(req, ERRDOS, ERRnoaccess);
7112 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
7113 "pid %u, file %s\n", (double)offset, (double)count,
7114 (unsigned int)lock_pid, fsp->fsp_name ));
7116 status = do_unlock(smbd_messaging_context(),
7123 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
7124 nt_errstr(status)));
7126 if (NT_STATUS_V(status)) {
7127 END_PROFILE(SMBlockingX);
7128 reply_nterror(req, status);
7133 /* Setup the timeout in seconds. */
7135 if (!lp_blocking_locks(SNUM(conn))) {
7139 /* Now do any requested locks */
7140 data += ((large_file_format ? 20 : 10)*num_ulocks);
7142 /* Data now points at the beginning of the list
7143 of smb_lkrng structs */
7145 for(i = 0; i < (int)num_locks; i++) {
7146 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
7147 READ_LOCK:WRITE_LOCK);
7148 lock_pid = get_lock_pid( data, i, large_file_format);
7149 count = get_lock_count( data, i, large_file_format);
7150 offset = get_lock_offset( data, i, large_file_format, &err);
7153 * There is no error code marked "stupid client bug".... :-).
7156 END_PROFILE(SMBlockingX);
7157 reply_doserror(req, ERRDOS, ERRnoaccess);
7161 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
7162 "%u, file %s timeout = %d\n", (double)offset,
7163 (double)count, (unsigned int)lock_pid,
7164 fsp->fsp_name, (int)lock_timeout ));
7166 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7167 struct blocking_lock_record *blr = NULL;
7169 if (lp_blocking_locks(SNUM(conn))) {
7171 /* Schedule a message to ourselves to
7172 remove the blocking lock record and
7173 return the right error. */
7175 blr = blocking_lock_cancel(fsp,
7181 NT_STATUS_FILE_LOCK_CONFLICT);
7183 END_PROFILE(SMBlockingX);
7188 ERRcancelviolation));
7192 /* Remove a matching pending lock. */
7193 status = do_lock_cancel(fsp,
7200 bool blocking_lock = lock_timeout ? True : False;
7201 bool defer_lock = False;
7202 struct byte_range_lock *br_lck;
7203 uint32 block_smbpid;
7205 br_lck = do_lock(smbd_messaging_context(),
7217 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7218 /* Windows internal resolution for blocking locks seems
7219 to be about 200ms... Don't wait for less than that. JRA. */
7220 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7221 lock_timeout = lp_lock_spin_time();
7226 /* This heuristic seems to match W2K3 very well. If a
7227 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7228 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7229 far as I can tell. Replacement for do_lock_spin(). JRA. */
7231 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7232 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7234 lock_timeout = lp_lock_spin_time();
7237 if (br_lck && defer_lock) {
7239 * A blocking lock was requested. Package up
7240 * this smb into a queued request and push it
7241 * onto the blocking lock queue.
7243 if(push_blocking_lock_request(br_lck,
7254 TALLOC_FREE(br_lck);
7255 END_PROFILE(SMBlockingX);
7260 TALLOC_FREE(br_lck);
7263 if (NT_STATUS_V(status)) {
7264 END_PROFILE(SMBlockingX);
7265 reply_nterror(req, status);
7270 /* If any of the above locks failed, then we must unlock
7271 all of the previous locks (X/Open spec). */
7273 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7277 * Ensure we don't do a remove on the lock that just failed,
7278 * as under POSIX rules, if we have a lock already there, we
7279 * will delete it (and we shouldn't) .....
7281 for(i--; i >= 0; i--) {
7282 lock_pid = get_lock_pid( data, i, large_file_format);
7283 count = get_lock_count( data, i, large_file_format);
7284 offset = get_lock_offset( data, i, large_file_format,
7288 * There is no error code marked "stupid client
7292 END_PROFILE(SMBlockingX);
7293 reply_doserror(req, ERRDOS, ERRnoaccess);
7297 do_unlock(smbd_messaging_context(),
7304 END_PROFILE(SMBlockingX);
7305 reply_nterror(req, status);
7309 reply_outbuf(req, 2, 0);
7311 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7312 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7314 END_PROFILE(SMBlockingX);
7319 #define DBGC_CLASS DBGC_ALL
7321 /****************************************************************************
7322 Reply to a SMBreadbmpx (read block multiplex) request.
7323 Always reply with an error, if someone has a platform really needs this,
7324 please contact vl@samba.org
7325 ****************************************************************************/
7327 void reply_readbmpx(struct smb_request *req)
7329 START_PROFILE(SMBreadBmpx);
7330 reply_doserror(req, ERRSRV, ERRuseSTD);
7331 END_PROFILE(SMBreadBmpx);
7335 /****************************************************************************
7336 Reply to a SMBreadbs (read block multiplex secondary) request.
7337 Always reply with an error, if someone has a platform really needs this,
7338 please contact vl@samba.org
7339 ****************************************************************************/
7341 void reply_readbs(struct smb_request *req)
7343 START_PROFILE(SMBreadBs);
7344 reply_doserror(req, ERRSRV, ERRuseSTD);
7345 END_PROFILE(SMBreadBs);
7349 /****************************************************************************
7350 Reply to a SMBsetattrE.
7351 ****************************************************************************/
7353 void reply_setattrE(struct smb_request *req)
7355 connection_struct *conn = req->conn;
7356 struct smb_file_time ft;
7358 SMB_STRUCT_STAT sbuf;
7361 START_PROFILE(SMBsetattrE);
7365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7366 END_PROFILE(SMBsetattrE);
7370 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7372 if(!fsp || (fsp->conn != conn)) {
7373 reply_doserror(req, ERRDOS, ERRbadfid);
7374 END_PROFILE(SMBsetattrE);
7380 * Convert the DOS times into unix times.
7383 ft.atime = convert_time_t_to_timespec(
7384 srv_make_unix_date2(req->vwv+3));
7385 ft.mtime = convert_time_t_to_timespec(
7386 srv_make_unix_date2(req->vwv+5));
7387 ft.create_time = convert_time_t_to_timespec(
7388 srv_make_unix_date2(req->vwv+1));
7390 reply_outbuf(req, 0, 0);
7393 * Patch from Ray Frush <frush@engr.colostate.edu>
7394 * Sometimes times are sent as zero - ignore them.
7397 /* Ensure we have a valid stat struct for the source. */
7398 if (fsp->fh->fd != -1) {
7399 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7400 status = map_nt_error_from_unix(errno);
7401 reply_nterror(req, status);
7402 END_PROFILE(SMBsetattrE);
7408 if (fsp->posix_open) {
7409 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
7411 ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
7414 status = map_nt_error_from_unix(errno);
7415 reply_nterror(req, status);
7416 END_PROFILE(SMBsetattrE);
7421 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7423 if (!NT_STATUS_IS_OK(status)) {
7424 reply_doserror(req, ERRDOS, ERRnoaccess);
7425 END_PROFILE(SMBsetattrE);
7429 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7432 (unsigned int)ft.atime.tv_sec,
7433 (unsigned int)ft.mtime.tv_sec,
7434 (unsigned int)ft.create_time.tv_sec
7437 END_PROFILE(SMBsetattrE);
7442 /* Back from the dead for OS/2..... JRA. */
7444 /****************************************************************************
7445 Reply to a SMBwritebmpx (write block multiplex primary) request.
7446 Always reply with an error, if someone has a platform really needs this,
7447 please contact vl@samba.org
7448 ****************************************************************************/
7450 void reply_writebmpx(struct smb_request *req)
7452 START_PROFILE(SMBwriteBmpx);
7453 reply_doserror(req, ERRSRV, ERRuseSTD);
7454 END_PROFILE(SMBwriteBmpx);
7458 /****************************************************************************
7459 Reply to a SMBwritebs (write block multiplex secondary) request.
7460 Always reply with an error, if someone has a platform really needs this,
7461 please contact vl@samba.org
7462 ****************************************************************************/
7464 void reply_writebs(struct smb_request *req)
7466 START_PROFILE(SMBwriteBs);
7467 reply_doserror(req, ERRSRV, ERRuseSTD);
7468 END_PROFILE(SMBwriteBs);
7472 /****************************************************************************
7473 Reply to a SMBgetattrE.
7474 ****************************************************************************/
7476 void reply_getattrE(struct smb_request *req)
7478 connection_struct *conn = req->conn;
7479 SMB_STRUCT_STAT sbuf;
7482 struct timespec create_ts;
7484 START_PROFILE(SMBgetattrE);
7487 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7488 END_PROFILE(SMBgetattrE);
7492 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7494 if(!fsp || (fsp->conn != conn)) {
7495 reply_doserror(req, ERRDOS, ERRbadfid);
7496 END_PROFILE(SMBgetattrE);
7500 /* Do an fstat on this file */
7501 if(fsp_stat(fsp, &sbuf)) {
7502 reply_unixerror(req, ERRDOS, ERRnoaccess);
7503 END_PROFILE(SMBgetattrE);
7507 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7510 * Convert the times into dos times. Set create
7511 * date to be last modify date as UNIX doesn't save
7515 reply_outbuf(req, 11, 0);
7517 create_ts = get_create_timespec(&sbuf,
7518 lp_fake_dir_create_times(SNUM(conn)));
7519 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7520 srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7521 /* Should we check pending modtime here ? JRA */
7522 srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7525 SIVAL(req->outbuf, smb_vwv6, 0);
7526 SIVAL(req->outbuf, smb_vwv8, 0);
7528 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7529 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7530 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7532 SSVAL(req->outbuf,smb_vwv10, mode);
7534 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7536 END_PROFILE(SMBgetattrE);