2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "smbd/globals.h"
30 extern enum protocol_types Protocol;
32 /****************************************************************************
33 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
34 path or anything including wildcards.
35 We're assuming here that '/' is not the second byte in any multibyte char
36 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
38 ****************************************************************************/
40 /* Custom version for processing POSIX paths. */
41 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
43 static NTSTATUS check_path_syntax_internal(char *path,
45 bool *p_last_component_contains_wcard)
49 NTSTATUS ret = NT_STATUS_OK;
50 bool start_of_name_component = True;
51 bool stream_started = false;
53 *p_last_component_contains_wcard = False;
60 return NT_STATUS_OBJECT_NAME_INVALID;
63 return NT_STATUS_OBJECT_NAME_INVALID;
65 if (strchr_m(&s[1], ':')) {
66 return NT_STATUS_OBJECT_NAME_INVALID;
68 if (StrCaseCmp(s, ":$DATA") != 0) {
69 return NT_STATUS_INVALID_PARAMETER;
75 if (!posix_path && !stream_started && *s == ':') {
76 if (*p_last_component_contains_wcard) {
77 return NT_STATUS_OBJECT_NAME_INVALID;
79 /* Stream names allow more characters than file names.
80 We're overloading posix_path here to allow a wider
81 range of characters. If stream_started is true this
82 is still a Windows path even if posix_path is true.
85 stream_started = true;
86 start_of_name_component = false;
90 return NT_STATUS_OBJECT_NAME_INVALID;
94 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
96 * Safe to assume is not the second part of a mb char
97 * as this is handled below.
99 /* Eat multiple '/' or '\\' */
100 while (IS_PATH_SEP(*s,posix_path)) {
103 if ((d != path) && (*s != '\0')) {
104 /* We only care about non-leading or trailing '/' or '\\' */
108 start_of_name_component = True;
110 *p_last_component_contains_wcard = False;
114 if (start_of_name_component) {
115 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
116 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
119 * No mb char starts with '.' so we're safe checking the directory separator here.
122 /* If we just added a '/' - delete it */
123 if ((d > path) && (*(d-1) == '/')) {
128 /* Are we at the start ? Can't go back further if so. */
130 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
133 /* Go back one level... */
134 /* We know this is safe as '/' cannot be part of a mb sequence. */
135 /* NOTE - if this assumption is invalid we are not in good shape... */
136 /* Decrement d first as d points to the *next* char to write into. */
137 for (d--; d > path; d--) {
141 s += 2; /* Else go past the .. */
142 /* We're still at the start of a name component, just the previous one. */
145 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
157 if (*s <= 0x1f || *s == '|') {
158 return NT_STATUS_OBJECT_NAME_INVALID;
166 *p_last_component_contains_wcard = True;
175 /* Get the size of the next MB character. */
176 next_codepoint(s,&siz);
194 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
196 return NT_STATUS_INVALID_PARAMETER;
199 start_of_name_component = False;
207 /****************************************************************************
208 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
209 No wildcards allowed.
210 ****************************************************************************/
212 NTSTATUS check_path_syntax(char *path)
215 return check_path_syntax_internal(path, False, &ignore);
218 /****************************************************************************
219 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
220 Wildcards allowed - p_contains_wcard returns true if the last component contained
222 ****************************************************************************/
224 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
226 return check_path_syntax_internal(path, False, p_contains_wcard);
229 /****************************************************************************
230 Check the path for a POSIX client.
231 We're assuming here that '/' is not the second byte in any multibyte char
232 set (a safe assumption).
233 ****************************************************************************/
235 NTSTATUS check_path_syntax_posix(char *path)
238 return check_path_syntax_internal(path, True, &ignore);
241 /****************************************************************************
242 Pull a string and check the path allowing a wilcard - provide for error return.
243 ****************************************************************************/
245 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
246 const char *base_ptr,
253 bool *contains_wcard)
259 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
263 *err = NT_STATUS_INVALID_PARAMETER;
267 *contains_wcard = False;
269 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
271 * For a DFS path the function parse_dfs_path()
272 * will do the path processing, just make a copy.
278 if (lp_posix_pathnames()) {
279 *err = check_path_syntax_posix(*pp_dest);
281 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
287 /****************************************************************************
288 Pull a string and check the path - provide for error return.
289 ****************************************************************************/
291 size_t srvstr_get_path(TALLOC_CTX *ctx,
292 const char *base_ptr,
301 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
302 src_len, flags, err, &ignore);
305 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
306 char **pp_dest, const char *src, int flags,
307 NTSTATUS *err, bool *contains_wcard)
309 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
310 pp_dest, src, smbreq_bufrem(req, src),
311 flags, err, contains_wcard);
314 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
315 char **pp_dest, const char *src, int flags,
319 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
320 flags, err, &ignore);
323 /****************************************************************************
324 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
325 ****************************************************************************/
327 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
330 if (!(fsp) || !(conn)) {
331 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
334 if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
335 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
341 /****************************************************************************
342 Check if we have a correct fsp pointing to a file.
343 ****************************************************************************/
345 bool check_fsp(connection_struct *conn, struct smb_request *req,
348 if (!check_fsp_open(conn, req, fsp)) {
351 if ((fsp)->is_directory) {
352 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
355 if ((fsp)->fh->fd == -1) {
356 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
359 (fsp)->num_smb_operations++;
363 /****************************************************************************
364 Check if we have a correct fsp pointing to a quota fake file. Replacement for
365 the CHECK_NTQUOTA_HANDLE_OK macro.
366 ****************************************************************************/
368 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
371 if (!check_fsp_open(conn, req, fsp)) {
375 if (fsp->is_directory) {
379 if (fsp->fake_file_handle == NULL) {
383 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
387 if (fsp->fake_file_handle->private_data == NULL) {
394 /****************************************************************************
395 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
396 ****************************************************************************/
398 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
401 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
402 && (req->vuid == (fsp)->vuid)) {
406 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
410 static bool netbios_session_retarget(const char *name, int name_type)
413 char *trim_name_type;
414 const char *retarget_parm;
417 int retarget_type = 0x20;
418 int retarget_port = 139;
419 struct sockaddr_storage retarget_addr;
420 struct sockaddr_in *in_addr;
424 if (get_socket_port(smbd_server_fd()) != 139) {
428 trim_name = talloc_strdup(talloc_tos(), name);
429 if (trim_name == NULL) {
432 trim_char(trim_name, ' ', ' ');
434 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
436 if (trim_name_type == NULL) {
440 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
441 trim_name_type, NULL);
442 if (retarget_parm == NULL) {
443 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
446 if (retarget_parm == NULL) {
450 retarget = talloc_strdup(trim_name, retarget_parm);
451 if (retarget == NULL) {
455 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
457 p = strchr(retarget, ':');
460 retarget_port = atoi(p);
463 p = strchr_m(retarget, '#');
466 sscanf(p, "%x", &retarget_type);
469 ret = resolve_name(retarget, &retarget_addr, retarget_type);
471 DEBUG(10, ("could not resolve %s\n", retarget));
475 if (retarget_addr.ss_family != AF_INET) {
476 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
480 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
482 _smb_setlen(outbuf, 6);
483 SCVAL(outbuf, 0, 0x84);
484 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
485 *(uint16_t *)(outbuf+8) = htons(retarget_port);
487 if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
489 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
495 TALLOC_FREE(trim_name);
499 /****************************************************************************
500 Reply to a (netbios-level) special message.
501 ****************************************************************************/
503 void reply_special(char *inbuf)
505 int msg_type = CVAL(inbuf,0);
506 int msg_flags = CVAL(inbuf,1);
508 char name_type1, name_type2;
511 * We only really use 4 bytes of the outbuf, but for the smb_setlen
512 * calculation & friends (srv_send_smb uses that) we need the full smb
515 char outbuf[smb_size];
519 memset(outbuf, '\0', sizeof(outbuf));
521 smb_setlen(outbuf,0);
524 case 0x81: /* session request */
526 if (already_got_session) {
527 exit_server_cleanly("multiple session request not permitted");
530 SCVAL(outbuf,0,0x82);
532 if (name_len(inbuf+4) > 50 ||
533 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
534 DEBUG(0,("Invalid name length in session request\n"));
537 name_type1 = name_extract(inbuf,4,name1);
538 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
539 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
540 name1, name_type1, name2, name_type2));
542 if (netbios_session_retarget(name1, name_type1)) {
543 exit_server_cleanly("retargeted client");
546 set_local_machine_name(name1, True);
547 set_remote_machine_name(name2, True);
549 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
550 get_local_machine_name(), get_remote_machine_name(),
553 if (name_type2 == 'R') {
554 /* We are being asked for a pathworks session ---
556 SCVAL(outbuf, 0,0x83);
560 /* only add the client's machine name to the list
561 of possibly valid usernames if we are operating
562 in share mode security */
563 if (lp_security() == SEC_SHARE) {
564 add_session_user(get_remote_machine_name());
567 reload_services(True);
570 already_got_session = True;
573 case 0x89: /* session keepalive request
574 (some old clients produce this?) */
575 SCVAL(outbuf,0,SMBkeepalive);
579 case 0x82: /* positive session response */
580 case 0x83: /* negative session response */
581 case 0x84: /* retarget session response */
582 DEBUG(0,("Unexpected session response\n"));
585 case SMBkeepalive: /* session keepalive */
590 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
591 msg_type, msg_flags));
593 srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
597 /****************************************************************************
599 conn POINTER CAN BE NULL HERE !
600 ****************************************************************************/
602 void reply_tcon(struct smb_request *req)
604 connection_struct *conn = req->conn;
606 char *service_buf = NULL;
607 char *password = NULL;
612 DATA_BLOB password_blob;
613 TALLOC_CTX *ctx = talloc_tos();
615 START_PROFILE(SMBtcon);
617 if (req->buflen < 4) {
618 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
619 END_PROFILE(SMBtcon);
623 p = (const char *)req->buf + 1;
624 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
626 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
628 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
631 if (service_buf == NULL || password == NULL || dev == NULL) {
632 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
633 END_PROFILE(SMBtcon);
636 p = strrchr_m(service_buf,'\\');
640 service = service_buf;
643 password_blob = data_blob(password, pwlen+1);
645 conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
648 data_blob_clear_free(&password_blob);
651 reply_nterror(req, nt_status);
652 END_PROFILE(SMBtcon);
656 reply_outbuf(req, 2, 0);
657 SSVAL(req->outbuf,smb_vwv0,max_recv);
658 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
659 SSVAL(req->outbuf,smb_tid,conn->cnum);
661 DEBUG(3,("tcon service=%s cnum=%d\n",
662 service, conn->cnum));
664 END_PROFILE(SMBtcon);
668 /****************************************************************************
669 Reply to a tcon and X.
670 conn POINTER CAN BE NULL HERE !
671 ****************************************************************************/
673 void reply_tcon_and_X(struct smb_request *req)
675 connection_struct *conn = req->conn;
676 const char *service = NULL;
678 TALLOC_CTX *ctx = talloc_tos();
679 /* what the cleint thinks the device is */
680 char *client_devicetype = NULL;
681 /* what the server tells the client the share represents */
682 const char *server_devicetype;
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 + ret, '\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 #define SHORT_SEND_BUFSIZE 1024
2787 if (nread < headersize) {
2788 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2789 "header for file %s (%s). Terminating\n",
2790 fsp->fsp_name, strerror(errno) ));
2791 exit_server_cleanly("sendfile_short_send failed");
2794 nread -= headersize;
2796 if (nread < smb_maxcnt) {
2797 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2799 exit_server_cleanly("sendfile_short_send: "
2803 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2804 "with zeros !\n", fsp->fsp_name));
2806 while (nread < smb_maxcnt) {
2808 * We asked for the real file size and told sendfile
2809 * to not go beyond the end of the file. But it can
2810 * happen that in between our fstat call and the
2811 * sendfile call the file was truncated. This is very
2812 * bad because we have already announced the larger
2813 * number of bytes to the client.
2815 * The best we can do now is to send 0-bytes, just as
2816 * a read from a hole in a sparse file would do.
2818 * This should happen rarely enough that I don't care
2819 * about efficiency here :-)
2823 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2824 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2825 exit_server_cleanly("sendfile_short_send: "
2826 "write_data failed");
2833 #endif /* defined WITH_SENDFILE */
2835 /****************************************************************************
2836 Return a readbraw error (4 bytes of zero).
2837 ****************************************************************************/
2839 static void reply_readbraw_error(void)
2843 if (write_data(smbd_server_fd(),header,4) != 4) {
2848 /****************************************************************************
2849 Use sendfile in readbraw.
2850 ****************************************************************************/
2852 static void send_file_readbraw(connection_struct *conn,
2853 struct smb_request *req,
2859 char *outbuf = NULL;
2862 #if defined(WITH_SENDFILE)
2864 * We can only use sendfile on a non-chained packet
2865 * but we can use on a non-oplocked file. tridge proved this
2866 * on a train in Germany :-). JRA.
2867 * reply_readbraw has already checked the length.
2870 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2871 (fsp->wcp == NULL) &&
2872 lp_use_sendfile(SNUM(conn), smbd_server_conn->signing_state) ) {
2873 ssize_t sendfile_read = -1;
2875 DATA_BLOB header_blob;
2877 _smb_setlen(header,nread);
2878 header_blob = data_blob_const(header, 4);
2880 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2881 &header_blob, startpos, nread)) == -1) {
2882 /* Returning ENOSYS means no data at all was sent.
2883 * Do this as a normal read. */
2884 if (errno == ENOSYS) {
2885 goto normal_readbraw;
2889 * Special hack for broken Linux with no working sendfile. If we
2890 * return EINTR we sent the header but not the rest of the data.
2891 * Fake this up by doing read/write calls.
2893 if (errno == EINTR) {
2894 /* Ensure we don't do this again. */
2895 set_use_sendfile(SNUM(conn), False);
2896 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2898 if (fake_sendfile(fsp, startpos, nread) == -1) {
2899 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2900 fsp->fsp_name, strerror(errno) ));
2901 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2906 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2907 fsp->fsp_name, strerror(errno) ));
2908 exit_server_cleanly("send_file_readbraw sendfile failed");
2909 } else if (sendfile_read == 0) {
2911 * Some sendfile implementations return 0 to indicate
2912 * that there was a short read, but nothing was
2913 * actually written to the socket. In this case,
2914 * fallback to the normal read path so the header gets
2915 * the correct byte count.
2917 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2918 "bytes falling back to the normal read: "
2919 "%s\n", fsp->fsp_name));
2920 goto normal_readbraw;
2923 /* Deal with possible short send. */
2924 if (sendfile_read != 4+nread) {
2925 sendfile_short_send(fsp, sendfile_read, 4, nread);
2933 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2935 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2936 (unsigned)(nread+4)));
2937 reply_readbraw_error();
2942 ret = read_file(fsp,outbuf+4,startpos,nread);
2943 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2952 _smb_setlen(outbuf,ret);
2953 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2956 TALLOC_FREE(outbuf);
2959 /****************************************************************************
2960 Reply to a readbraw (core+ protocol).
2961 ****************************************************************************/
2963 void reply_readbraw(struct smb_request *req)
2965 connection_struct *conn = req->conn;
2966 ssize_t maxcount,mincount;
2970 struct lock_struct lock;
2974 START_PROFILE(SMBreadbraw);
2976 if (srv_is_signing_active(smbd_server_conn) ||
2977 is_encrypted_packet(req->inbuf)) {
2978 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2979 "raw reads/writes are disallowed.");
2983 reply_readbraw_error();
2984 END_PROFILE(SMBreadbraw);
2989 * Special check if an oplock break has been issued
2990 * and the readraw request croses on the wire, we must
2991 * return a zero length response here.
2994 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2997 * We have to do a check_fsp by hand here, as
2998 * we must always return 4 zero bytes on error,
3002 if (!fsp || !conn || conn != fsp->conn ||
3003 req->vuid != fsp->vuid ||
3004 fsp->is_directory || fsp->fh->fd == -1) {
3006 * fsp could be NULL here so use the value from the packet. JRA.
3008 DEBUG(3,("reply_readbraw: fnum %d not valid "
3010 (int)SVAL(req->vwv+0, 0)));
3011 reply_readbraw_error();
3012 END_PROFILE(SMBreadbraw);
3016 /* Do a "by hand" version of CHECK_READ. */
3017 if (!(fsp->can_read ||
3018 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3019 (fsp->access_mask & FILE_EXECUTE)))) {
3020 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3021 (int)SVAL(req->vwv+0, 0)));
3022 reply_readbraw_error();
3023 END_PROFILE(SMBreadbraw);
3027 flush_write_cache(fsp, READRAW_FLUSH);
3029 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3030 if(req->wct == 10) {
3032 * This is a large offset (64 bit) read.
3034 #ifdef LARGE_SMB_OFF_T
3036 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3038 #else /* !LARGE_SMB_OFF_T */
3041 * Ensure we haven't been sent a >32 bit offset.
3044 if(IVAL(req->vwv+8, 0) != 0) {
3045 DEBUG(0,("reply_readbraw: large offset "
3046 "(%x << 32) used and we don't support "
3047 "64 bit offsets.\n",
3048 (unsigned int)IVAL(req->vwv+8, 0) ));
3049 reply_readbraw_error();
3050 END_PROFILE(SMBreadbraw);
3054 #endif /* LARGE_SMB_OFF_T */
3057 DEBUG(0,("reply_readbraw: negative 64 bit "
3058 "readraw offset (%.0f) !\n",
3059 (double)startpos ));
3060 reply_readbraw_error();
3061 END_PROFILE(SMBreadbraw);
3066 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3067 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3069 /* ensure we don't overrun the packet size */
3070 maxcount = MIN(65535,maxcount);
3072 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3073 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3076 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3077 reply_readbraw_error();
3078 END_PROFILE(SMBreadbraw);
3082 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3086 if (startpos >= size) {
3089 nread = MIN(maxcount,(size - startpos));
3092 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3093 if (nread < mincount)
3097 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3098 "min=%lu nread=%lu\n",
3099 fsp->fnum, (double)startpos,
3100 (unsigned long)maxcount,
3101 (unsigned long)mincount,
3102 (unsigned long)nread ) );
3104 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3106 DEBUG(5,("reply_readbraw finished\n"));
3108 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3110 END_PROFILE(SMBreadbraw);
3115 #define DBGC_CLASS DBGC_LOCKING
3117 /****************************************************************************
3118 Reply to a lockread (core+ protocol).
3119 ****************************************************************************/
3121 void reply_lockread(struct smb_request *req)
3123 connection_struct *conn = req->conn;
3130 struct byte_range_lock *br_lck = NULL;
3133 START_PROFILE(SMBlockread);
3136 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3137 END_PROFILE(SMBlockread);
3141 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3143 if (!check_fsp(conn, req, fsp)) {
3144 END_PROFILE(SMBlockread);
3148 if (!CHECK_READ(fsp,req)) {
3149 reply_doserror(req, ERRDOS, ERRbadaccess);
3150 END_PROFILE(SMBlockread);
3154 numtoread = SVAL(req->vwv+1, 0);
3155 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3157 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3159 reply_outbuf(req, 5, numtoread + 3);
3161 data = smb_buf(req->outbuf) + 3;
3164 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3165 * protocol request that predates the read/write lock concept.
3166 * Thus instead of asking for a read lock here we need to ask
3167 * for a write lock. JRA.
3168 * Note that the requested lock size is unaffected by max_recv.
3171 br_lck = do_lock(smbd_messaging_context(),
3174 (uint64_t)numtoread,
3178 False, /* Non-blocking lock. */
3182 TALLOC_FREE(br_lck);
3184 if (NT_STATUS_V(status)) {
3185 reply_nterror(req, status);
3186 END_PROFILE(SMBlockread);
3191 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3194 if (numtoread > max_recv) {
3195 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3196 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3197 (unsigned int)numtoread, (unsigned int)max_recv ));
3198 numtoread = MIN(numtoread,max_recv);
3200 nread = read_file(fsp,data,startpos,numtoread);
3203 reply_unixerror(req, ERRDOS, ERRnoaccess);
3204 END_PROFILE(SMBlockread);
3208 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3210 SSVAL(req->outbuf,smb_vwv0,nread);
3211 SSVAL(req->outbuf,smb_vwv5,nread+3);
3212 p = smb_buf(req->outbuf);
3213 SCVAL(p,0,0); /* pad byte. */
3216 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3217 fsp->fnum, (int)numtoread, (int)nread));
3219 END_PROFILE(SMBlockread);
3224 #define DBGC_CLASS DBGC_ALL
3226 /****************************************************************************
3228 ****************************************************************************/
3230 void reply_read(struct smb_request *req)
3232 connection_struct *conn = req->conn;
3239 struct lock_struct lock;
3241 START_PROFILE(SMBread);
3244 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3245 END_PROFILE(SMBread);
3249 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3251 if (!check_fsp(conn, req, fsp)) {
3252 END_PROFILE(SMBread);
3256 if (!CHECK_READ(fsp,req)) {
3257 reply_doserror(req, ERRDOS, ERRbadaccess);
3258 END_PROFILE(SMBread);
3262 numtoread = SVAL(req->vwv+1, 0);
3263 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3265 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3268 * The requested read size cannot be greater than max_recv. JRA.
3270 if (numtoread > max_recv) {
3271 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3272 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3273 (unsigned int)numtoread, (unsigned int)max_recv ));
3274 numtoread = MIN(numtoread,max_recv);
3277 reply_outbuf(req, 5, numtoread+3);
3279 data = smb_buf(req->outbuf) + 3;
3281 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3282 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3285 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3286 reply_doserror(req, ERRDOS,ERRlock);
3287 END_PROFILE(SMBread);
3292 nread = read_file(fsp,data,startpos,numtoread);
3295 reply_unixerror(req, ERRDOS,ERRnoaccess);
3299 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3301 SSVAL(req->outbuf,smb_vwv0,nread);
3302 SSVAL(req->outbuf,smb_vwv5,nread+3);
3303 SCVAL(smb_buf(req->outbuf),0,1);
3304 SSVAL(smb_buf(req->outbuf),1,nread);
3306 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3307 fsp->fnum, (int)numtoread, (int)nread ) );
3310 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3312 END_PROFILE(SMBread);
3316 /****************************************************************************
3318 ****************************************************************************/
3320 static int setup_readX_header(struct smb_request *req, char *outbuf,
3326 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3327 data = smb_buf(outbuf);
3329 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3331 SCVAL(outbuf,smb_vwv0,0xFF);
3332 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3333 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3334 SSVAL(outbuf,smb_vwv6,
3336 + 1 /* the wct field */
3337 + 12 * sizeof(uint16_t) /* vwv */
3338 + 2); /* the buflen field */
3339 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3340 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3341 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3342 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3346 /****************************************************************************
3347 Reply to a read and X - possibly using sendfile.
3348 ****************************************************************************/
3350 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3351 files_struct *fsp, SMB_OFF_T startpos,
3354 SMB_STRUCT_STAT sbuf;
3356 struct lock_struct lock;
3358 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3359 reply_unixerror(req, ERRDOS, ERRnoaccess);
3363 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3364 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3367 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3368 reply_doserror(req, ERRDOS, ERRlock);
3372 if (!S_ISREG(sbuf.st_mode) || (startpos > sbuf.st_size)
3373 || (smb_maxcnt > (sbuf.st_size - startpos))) {
3375 * We already know that we would do a short read, so don't
3376 * try the sendfile() path.
3378 goto nosendfile_read;
3381 #if defined(WITH_SENDFILE)
3383 * We can only use sendfile on a non-chained packet
3384 * but we can use on a non-oplocked file. tridge proved this
3385 * on a train in Germany :-). JRA.
3388 if (!req_is_in_chain(req) &&
3389 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3390 (fsp->wcp == NULL) &&
3391 lp_use_sendfile(SNUM(conn), smbd_server_conn->signing_state) ) {
3392 uint8 headerbuf[smb_size + 12 * 2];
3396 * Set up the packet header before send. We
3397 * assume here the sendfile will work (get the
3398 * correct amount of data).
3401 header = data_blob_const(headerbuf, sizeof(headerbuf));
3403 construct_reply_common_req(req, (char *)headerbuf);
3404 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3406 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3407 /* Returning ENOSYS means no data at all was sent.
3408 Do this as a normal read. */
3409 if (errno == ENOSYS) {
3414 * Special hack for broken Linux with no working sendfile. If we
3415 * return EINTR we sent the header but not the rest of the data.
3416 * Fake this up by doing read/write calls.
3419 if (errno == EINTR) {
3420 /* Ensure we don't do this again. */
3421 set_use_sendfile(SNUM(conn), False);
3422 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3423 nread = fake_sendfile(fsp, startpos,
3426 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3427 fsp->fsp_name, strerror(errno) ));
3428 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3430 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3431 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3432 /* No outbuf here means successful sendfile. */
3436 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3437 fsp->fsp_name, strerror(errno) ));
3438 exit_server_cleanly("send_file_readX sendfile failed");
3439 } else if (nread == 0) {
3441 * Some sendfile implementations return 0 to indicate
3442 * that there was a short read, but nothing was
3443 * actually written to the socket. In this case,
3444 * fallback to the normal read path so the header gets
3445 * the correct byte count.
3447 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3448 "falling back to the normal read: %s\n",
3453 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3454 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3456 /* Deal with possible short send. */
3457 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3458 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3460 /* No outbuf here means successful sendfile. */
3461 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3462 SMB_PERFCOUNT_END(&req->pcd);
3470 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3471 uint8 headerbuf[smb_size + 2*12];
3473 construct_reply_common_req(req, (char *)headerbuf);
3474 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3476 /* Send out the header. */
3477 if (write_data(smbd_server_fd(), (char *)headerbuf,
3478 sizeof(headerbuf)) != sizeof(headerbuf)) {
3479 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3480 fsp->fsp_name, strerror(errno) ));
3481 exit_server_cleanly("send_file_readX sendfile failed");
3483 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3485 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3486 fsp->fsp_name, strerror(errno) ));
3487 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3494 reply_outbuf(req, 12, smb_maxcnt);
3496 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3498 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3501 reply_unixerror(req, ERRDOS, ERRnoaccess);
3505 setup_readX_header(req, (char *)req->outbuf, nread);
3507 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3508 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3514 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3515 TALLOC_FREE(req->outbuf);
3519 /****************************************************************************
3520 Reply to a read and X.
3521 ****************************************************************************/
3523 void reply_read_and_X(struct smb_request *req)
3525 connection_struct *conn = req->conn;
3529 bool big_readX = False;
3531 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3534 START_PROFILE(SMBreadX);
3536 if ((req->wct != 10) && (req->wct != 12)) {
3537 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3541 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3542 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3543 smb_maxcnt = SVAL(req->vwv+5, 0);
3545 /* If it's an IPC, pass off the pipe handler. */
3547 reply_pipe_read_and_X(req);
3548 END_PROFILE(SMBreadX);
3552 if (!check_fsp(conn, req, fsp)) {
3553 END_PROFILE(SMBreadX);
3557 if (!CHECK_READ(fsp,req)) {
3558 reply_doserror(req, ERRDOS,ERRbadaccess);
3559 END_PROFILE(SMBreadX);
3563 if (global_client_caps & CAP_LARGE_READX) {
3564 size_t upper_size = SVAL(req->vwv+7, 0);
3565 smb_maxcnt |= (upper_size<<16);
3566 if (upper_size > 1) {
3567 /* Can't do this on a chained packet. */
3568 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3569 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3570 END_PROFILE(SMBreadX);
3573 /* We currently don't do this on signed or sealed data. */
3574 if (srv_is_signing_active(smbd_server_conn) ||
3575 is_encrypted_packet(req->inbuf)) {
3576 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3577 END_PROFILE(SMBreadX);
3580 /* Is there room in the reply for this data ? */
3581 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3583 NT_STATUS_INVALID_PARAMETER);
3584 END_PROFILE(SMBreadX);
3591 if (req->wct == 12) {
3592 #ifdef LARGE_SMB_OFF_T
3594 * This is a large offset (64 bit) read.
3596 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3598 #else /* !LARGE_SMB_OFF_T */
3601 * Ensure we haven't been sent a >32 bit offset.
3604 if(IVAL(req->vwv+10, 0) != 0) {
3605 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3606 "used and we don't support 64 bit offsets.\n",
3607 (unsigned int)IVAL(req->vwv+10, 0) ));
3608 END_PROFILE(SMBreadX);
3609 reply_doserror(req, ERRDOS, ERRbadaccess);
3613 #endif /* LARGE_SMB_OFF_T */
3618 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3622 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3625 END_PROFILE(SMBreadX);
3629 /****************************************************************************
3630 Error replies to writebraw must have smb_wct == 1. Fix this up.
3631 ****************************************************************************/
3633 void error_to_writebrawerr(struct smb_request *req)
3635 uint8 *old_outbuf = req->outbuf;
3637 reply_outbuf(req, 1, 0);
3639 memcpy(req->outbuf, old_outbuf, smb_size);
3640 TALLOC_FREE(old_outbuf);
3643 /****************************************************************************
3644 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3645 ****************************************************************************/
3647 void reply_writebraw(struct smb_request *req)
3649 connection_struct *conn = req->conn;
3652 ssize_t total_written=0;
3653 size_t numtowrite=0;
3659 struct lock_struct lock;
3662 START_PROFILE(SMBwritebraw);
3665 * If we ever reply with an error, it must have the SMB command
3666 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3669 SCVAL(req->inbuf,smb_com,SMBwritec);
3671 if (srv_is_signing_active(smbd_server_conn)) {
3672 END_PROFILE(SMBwritebraw);
3673 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3674 "raw reads/writes are disallowed.");
3677 if (req->wct < 12) {
3678 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3679 error_to_writebrawerr(req);
3680 END_PROFILE(SMBwritebraw);
3684 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3685 if (!check_fsp(conn, req, fsp)) {
3686 error_to_writebrawerr(req);
3687 END_PROFILE(SMBwritebraw);
3691 if (!CHECK_WRITE(fsp)) {
3692 reply_doserror(req, ERRDOS, ERRbadaccess);
3693 error_to_writebrawerr(req);
3694 END_PROFILE(SMBwritebraw);
3698 tcount = IVAL(req->vwv+1, 0);
3699 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3700 write_through = BITSETW(req->vwv+7,0);
3702 /* We have to deal with slightly different formats depending
3703 on whether we are using the core+ or lanman1.0 protocol */
3705 if(Protocol <= PROTOCOL_COREPLUS) {
3706 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3707 data = smb_buf(req->inbuf);
3709 numtowrite = SVAL(req->vwv+10, 0);
3710 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3713 /* Ensure we don't write bytes past the end of this packet. */
3714 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3716 error_to_writebrawerr(req);
3717 END_PROFILE(SMBwritebraw);
3721 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3722 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3725 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3726 reply_doserror(req, ERRDOS, ERRlock);
3727 error_to_writebrawerr(req);
3728 END_PROFILE(SMBwritebraw);
3733 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3736 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3737 "wrote=%d sync=%d\n",
3738 fsp->fnum, (double)startpos, (int)numtowrite,
3739 (int)nwritten, (int)write_through));
3741 if (nwritten < (ssize_t)numtowrite) {
3742 reply_unixerror(req, ERRHRD, ERRdiskfull);
3743 error_to_writebrawerr(req);
3747 total_written = nwritten;
3749 /* Allocate a buffer of 64k + length. */
3750 buf = TALLOC_ARRAY(NULL, char, 65540);
3752 reply_doserror(req, ERRDOS, ERRnomem);
3753 error_to_writebrawerr(req);
3757 /* Return a SMBwritebraw message to the redirector to tell
3758 * it to send more bytes */
3760 memcpy(buf, req->inbuf, smb_size);
3761 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3762 SCVAL(buf,smb_com,SMBwritebraw);
3763 SSVALS(buf,smb_vwv0,0xFFFF);
3765 if (!srv_send_smb(smbd_server_fd(),
3767 false, 0, /* no signing */
3768 IS_CONN_ENCRYPTED(conn),
3770 exit_server_cleanly("reply_writebraw: srv_send_smb "
3774 /* Now read the raw data into the buffer and write it */
3775 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3777 if (!NT_STATUS_IS_OK(status)) {
3778 exit_server_cleanly("secondary writebraw failed");
3781 /* Set up outbuf to return the correct size */
3782 reply_outbuf(req, 1, 0);
3784 if (numtowrite != 0) {
3786 if (numtowrite > 0xFFFF) {
3787 DEBUG(0,("reply_writebraw: Oversize secondary write "
3788 "raw requested (%u). Terminating\n",
3789 (unsigned int)numtowrite ));
3790 exit_server_cleanly("secondary writebraw failed");
3793 if (tcount > nwritten+numtowrite) {
3794 DEBUG(3,("reply_writebraw: Client overestimated the "
3796 (int)tcount,(int)nwritten,(int)numtowrite));
3799 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3801 if (!NT_STATUS_IS_OK(status)) {
3802 DEBUG(0,("reply_writebraw: Oversize secondary write "
3803 "raw read failed (%s). Terminating\n",
3804 nt_errstr(status)));
3805 exit_server_cleanly("secondary writebraw failed");
3808 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3809 if (nwritten == -1) {
3811 reply_unixerror(req, ERRHRD, ERRdiskfull);
3812 error_to_writebrawerr(req);
3816 if (nwritten < (ssize_t)numtowrite) {
3817 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3818 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3822 total_written += nwritten;
3827 SSVAL(req->outbuf,smb_vwv0,total_written);
3829 status = sync_file(conn, fsp, write_through);
3830 if (!NT_STATUS_IS_OK(status)) {
3831 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3832 fsp->fsp_name, nt_errstr(status) ));
3833 reply_nterror(req, status);
3834 error_to_writebrawerr(req);
3838 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3840 fsp->fnum, (double)startpos, (int)numtowrite,
3841 (int)total_written));
3843 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3845 /* We won't return a status if write through is not selected - this
3846 * follows what WfWg does */
3847 END_PROFILE(SMBwritebraw);
3849 if (!write_through && total_written==tcount) {
3851 #if RABBIT_PELLET_FIX
3853 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3854 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3857 if (!send_keepalive(smbd_server_fd())) {
3858 exit_server_cleanly("reply_writebraw: send of "
3859 "keepalive failed");
3862 TALLOC_FREE(req->outbuf);
3867 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3869 END_PROFILE(SMBwritebraw);
3874 #define DBGC_CLASS DBGC_LOCKING
3876 /****************************************************************************
3877 Reply to a writeunlock (core+).
3878 ****************************************************************************/
3880 void reply_writeunlock(struct smb_request *req)
3882 connection_struct *conn = req->conn;
3883 ssize_t nwritten = -1;
3887 NTSTATUS status = NT_STATUS_OK;
3889 struct lock_struct lock;
3891 START_PROFILE(SMBwriteunlock);
3894 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3895 END_PROFILE(SMBwriteunlock);
3899 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3901 if (!check_fsp(conn, req, fsp)) {
3902 END_PROFILE(SMBwriteunlock);
3906 if (!CHECK_WRITE(fsp)) {
3907 reply_doserror(req, ERRDOS,ERRbadaccess);
3908 END_PROFILE(SMBwriteunlock);
3912 numtowrite = SVAL(req->vwv+1, 0);
3913 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3914 data = (const char *)req->buf + 3;
3917 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3918 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3921 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3922 reply_doserror(req, ERRDOS, ERRlock);
3923 END_PROFILE(SMBwriteunlock);
3928 /* The special X/Open SMB protocol handling of
3929 zero length writes is *NOT* done for
3931 if(numtowrite == 0) {
3934 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3937 status = sync_file(conn, fsp, False /* write through */);
3938 if (!NT_STATUS_IS_OK(status)) {
3939 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3940 fsp->fsp_name, nt_errstr(status) ));
3941 reply_nterror(req, status);
3945 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3946 reply_unixerror(req, ERRHRD, ERRdiskfull);
3951 status = do_unlock(smbd_messaging_context(),
3954 (uint64_t)numtowrite,
3958 if (NT_STATUS_V(status)) {
3959 reply_nterror(req, status);
3964 reply_outbuf(req, 1, 0);
3966 SSVAL(req->outbuf,smb_vwv0,nwritten);
3968 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3969 fsp->fnum, (int)numtowrite, (int)nwritten));
3973 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3976 END_PROFILE(SMBwriteunlock);
3981 #define DBGC_CLASS DBGC_ALL
3983 /****************************************************************************
3985 ****************************************************************************/
3987 void reply_write(struct smb_request *req)
3989 connection_struct *conn = req->conn;
3991 ssize_t nwritten = -1;
3995 struct lock_struct lock;
3998 START_PROFILE(SMBwrite);
4001 END_PROFILE(SMBwrite);
4002 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4006 /* If it's an IPC, pass off the pipe handler. */
4008 reply_pipe_write(req);
4009 END_PROFILE(SMBwrite);
4013 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4015 if (!check_fsp(conn, req, fsp)) {
4016 END_PROFILE(SMBwrite);
4020 if (!CHECK_WRITE(fsp)) {
4021 reply_doserror(req, ERRDOS, ERRbadaccess);
4022 END_PROFILE(SMBwrite);
4026 numtowrite = SVAL(req->vwv+1, 0);
4027 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4028 data = (const char *)req->buf + 3;
4030 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4031 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4034 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4035 reply_doserror(req, ERRDOS, ERRlock);
4036 END_PROFILE(SMBwrite);
4041 * X/Open SMB protocol says that if smb_vwv1 is
4042 * zero then the file size should be extended or
4043 * truncated to the size given in smb_vwv[2-3].
4046 if(numtowrite == 0) {
4048 * This is actually an allocate call, and set EOF. JRA.
4050 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4052 reply_nterror(req, NT_STATUS_DISK_FULL);
4055 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4057 reply_nterror(req, NT_STATUS_DISK_FULL);
4060 trigger_write_time_update_immediate(fsp);
4062 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4065 status = sync_file(conn, fsp, False);
4066 if (!NT_STATUS_IS_OK(status)) {
4067 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4068 fsp->fsp_name, nt_errstr(status) ));
4069 reply_nterror(req, status);
4073 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4074 reply_unixerror(req, ERRHRD, ERRdiskfull);
4078 reply_outbuf(req, 1, 0);
4080 SSVAL(req->outbuf,smb_vwv0,nwritten);
4082 if (nwritten < (ssize_t)numtowrite) {
4083 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4084 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4087 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4090 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4092 END_PROFILE(SMBwrite);
4096 /****************************************************************************
4097 Ensure a buffer is a valid writeX for recvfile purposes.
4098 ****************************************************************************/
4100 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4101 (2*14) + /* word count (including bcc) */ \
4104 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4107 connection_struct *conn = NULL;
4108 unsigned int doff = 0;
4109 size_t len = smb_len_large(inbuf);
4111 if (is_encrypted_packet(inbuf)) {
4112 /* Can't do this on encrypted
4117 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4121 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4122 CVAL(inbuf,smb_wct) != 14) {
4123 DEBUG(10,("is_valid_writeX_buffer: chained or "
4124 "invalid word length.\n"));
4128 conn = conn_find(SVAL(inbuf, smb_tid));
4130 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4134 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4137 if (IS_PRINT(conn)) {
4138 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4141 doff = SVAL(inbuf,smb_vwv11);
4143 numtowrite = SVAL(inbuf,smb_vwv10);
4145 if (len > doff && len - doff > 0xFFFF) {
4146 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4149 if (numtowrite == 0) {
4150 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4154 /* Ensure the sizes match up. */
4155 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4156 /* no pad byte...old smbclient :-( */
4157 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4159 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4163 if (len - doff != numtowrite) {
4164 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4165 "len = %u, doff = %u, numtowrite = %u\n",
4168 (unsigned int)numtowrite ));
4172 DEBUG(10,("is_valid_writeX_buffer: true "
4173 "len = %u, doff = %u, numtowrite = %u\n",
4176 (unsigned int)numtowrite ));
4181 /****************************************************************************
4182 Reply to a write and X.
4183 ****************************************************************************/
4185 void reply_write_and_X(struct smb_request *req)
4187 connection_struct *conn = req->conn;
4189 struct lock_struct lock;
4194 unsigned int smb_doff;
4195 unsigned int smblen;
4199 START_PROFILE(SMBwriteX);
4201 if ((req->wct != 12) && (req->wct != 14)) {
4202 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4203 END_PROFILE(SMBwriteX);
4207 numtowrite = SVAL(req->vwv+10, 0);
4208 smb_doff = SVAL(req->vwv+11, 0);
4209 smblen = smb_len(req->inbuf);
4211 if (req->unread_bytes > 0xFFFF ||
4212 (smblen > smb_doff &&
4213 smblen - smb_doff > 0xFFFF)) {
4214 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4217 if (req->unread_bytes) {
4218 /* Can't do a recvfile write on IPC$ */
4220 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4221 END_PROFILE(SMBwriteX);
4224 if (numtowrite != req->unread_bytes) {
4225 reply_doserror(req, ERRDOS, ERRbadmem);
4226 END_PROFILE(SMBwriteX);
4230 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4231 smb_doff + numtowrite > smblen) {
4232 reply_doserror(req, ERRDOS, ERRbadmem);
4233 END_PROFILE(SMBwriteX);
4238 /* If it's an IPC, pass off the pipe handler. */
4240 if (req->unread_bytes) {
4241 reply_doserror(req, ERRDOS, ERRbadmem);
4242 END_PROFILE(SMBwriteX);
4245 reply_pipe_write_and_X(req);
4246 END_PROFILE(SMBwriteX);
4250 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4251 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4252 write_through = BITSETW(req->vwv+7,0);
4254 if (!check_fsp(conn, req, fsp)) {
4255 END_PROFILE(SMBwriteX);
4259 if (!CHECK_WRITE(fsp)) {
4260 reply_doserror(req, ERRDOS, ERRbadaccess);
4261 END_PROFILE(SMBwriteX);
4265 data = smb_base(req->inbuf) + smb_doff;
4267 if(req->wct == 14) {
4268 #ifdef LARGE_SMB_OFF_T
4270 * This is a large offset (64 bit) write.
4272 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4274 #else /* !LARGE_SMB_OFF_T */
4277 * Ensure we haven't been sent a >32 bit offset.
4280 if(IVAL(req->vwv+12, 0) != 0) {
4281 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4282 "used and we don't support 64 bit offsets.\n",
4283 (unsigned int)IVAL(req->vwv+12, 0) ));
4284 reply_doserror(req, ERRDOS, ERRbadaccess);
4285 END_PROFILE(SMBwriteX);
4289 #endif /* LARGE_SMB_OFF_T */
4292 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4293 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4296 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4297 reply_doserror(req, ERRDOS, ERRlock);
4298 END_PROFILE(SMBwriteX);
4302 /* X/Open SMB protocol says that, unlike SMBwrite
4303 if the length is zero then NO truncation is
4304 done, just a write of zero. To truncate a file,
4307 if(numtowrite == 0) {
4311 if ((req->unread_bytes == 0) &&
4312 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4317 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4320 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4321 reply_unixerror(req, ERRHRD, ERRdiskfull);
4325 reply_outbuf(req, 6, 0);
4326 SSVAL(req->outbuf,smb_vwv2,nwritten);
4327 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4329 if (nwritten < (ssize_t)numtowrite) {
4330 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4331 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4334 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4335 fsp->fnum, (int)numtowrite, (int)nwritten));
4337 status = sync_file(conn, fsp, write_through);
4338 if (!NT_STATUS_IS_OK(status)) {
4339 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4340 fsp->fsp_name, nt_errstr(status) ));
4341 reply_nterror(req, status);
4345 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4347 END_PROFILE(SMBwriteX);
4352 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4354 END_PROFILE(SMBwriteX);
4358 /****************************************************************************
4360 ****************************************************************************/
4362 void reply_lseek(struct smb_request *req)
4364 connection_struct *conn = req->conn;
4370 START_PROFILE(SMBlseek);
4373 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4374 END_PROFILE(SMBlseek);
4378 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4380 if (!check_fsp(conn, req, fsp)) {
4384 flush_write_cache(fsp, SEEK_FLUSH);
4386 mode = SVAL(req->vwv+1, 0) & 3;
4387 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4388 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4397 res = fsp->fh->pos + startpos;
4408 if (umode == SEEK_END) {
4409 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4410 if(errno == EINVAL) {
4411 SMB_OFF_T current_pos = startpos;
4412 SMB_STRUCT_STAT sbuf;
4414 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4415 reply_unixerror(req, ERRDOS,
4417 END_PROFILE(SMBlseek);
4421 current_pos += sbuf.st_size;
4423 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4428 reply_unixerror(req, ERRDOS, ERRnoaccess);
4429 END_PROFILE(SMBlseek);
4436 reply_outbuf(req, 2, 0);
4437 SIVAL(req->outbuf,smb_vwv0,res);
4439 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4440 fsp->fnum, (double)startpos, (double)res, mode));
4442 END_PROFILE(SMBlseek);
4446 /****************************************************************************
4448 ****************************************************************************/
4450 void reply_flush(struct smb_request *req)
4452 connection_struct *conn = req->conn;
4456 START_PROFILE(SMBflush);
4459 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4463 fnum = SVAL(req->vwv+0, 0);
4464 fsp = file_fsp(req, fnum);
4466 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4471 file_sync_all(conn);
4473 NTSTATUS status = sync_file(conn, fsp, True);
4474 if (!NT_STATUS_IS_OK(status)) {
4475 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4476 fsp->fsp_name, nt_errstr(status) ));
4477 reply_nterror(req, status);
4478 END_PROFILE(SMBflush);
4483 reply_outbuf(req, 0, 0);
4485 DEBUG(3,("flush\n"));
4486 END_PROFILE(SMBflush);
4490 /****************************************************************************
4492 conn POINTER CAN BE NULL HERE !
4493 ****************************************************************************/
4495 void reply_exit(struct smb_request *req)
4497 START_PROFILE(SMBexit);
4499 file_close_pid(req->smbpid, req->vuid);
4501 reply_outbuf(req, 0, 0);
4503 DEBUG(3,("exit\n"));
4505 END_PROFILE(SMBexit);
4509 /****************************************************************************
4510 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4511 ****************************************************************************/
4513 void reply_close(struct smb_request *req)
4515 connection_struct *conn = req->conn;
4516 NTSTATUS status = NT_STATUS_OK;
4517 files_struct *fsp = NULL;
4518 START_PROFILE(SMBclose);
4521 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4522 END_PROFILE(SMBclose);
4526 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4529 * We can only use check_fsp if we know it's not a directory.
4532 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4533 reply_doserror(req, ERRDOS, ERRbadfid);
4534 END_PROFILE(SMBclose);
4538 if(fsp->is_directory) {
4540 * Special case - close NT SMB directory handle.
4542 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4543 status = close_file(req, fsp, NORMAL_CLOSE);
4547 * Close ordinary file.
4550 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4551 fsp->fh->fd, fsp->fnum,
4552 conn->num_files_open));
4555 * Take care of any time sent in the close.
4558 t = srv_make_unix_date3(req->vwv+1);
4559 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4562 * close_file() returns the unix errno if an error
4563 * was detected on close - normally this is due to
4564 * a disk full error. If not then it was probably an I/O error.
4567 status = close_file(req, fsp, NORMAL_CLOSE);
4570 if (!NT_STATUS_IS_OK(status)) {
4571 reply_nterror(req, status);
4572 END_PROFILE(SMBclose);
4576 reply_outbuf(req, 0, 0);
4577 END_PROFILE(SMBclose);
4581 /****************************************************************************
4582 Reply to a writeclose (Core+ protocol).
4583 ****************************************************************************/
4585 void reply_writeclose(struct smb_request *req)
4587 connection_struct *conn = req->conn;
4589 ssize_t nwritten = -1;
4590 NTSTATUS close_status = NT_STATUS_OK;
4593 struct timespec mtime;
4595 struct lock_struct lock;
4597 START_PROFILE(SMBwriteclose);
4600 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4601 END_PROFILE(SMBwriteclose);
4605 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4607 if (!check_fsp(conn, req, fsp)) {
4608 END_PROFILE(SMBwriteclose);
4611 if (!CHECK_WRITE(fsp)) {
4612 reply_doserror(req, ERRDOS,ERRbadaccess);
4613 END_PROFILE(SMBwriteclose);
4617 numtowrite = SVAL(req->vwv+1, 0);
4618 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4619 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4620 data = (const char *)req->buf + 1;
4623 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4624 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4627 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4628 reply_doserror(req, ERRDOS,ERRlock);
4629 END_PROFILE(SMBwriteclose);
4634 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4636 set_close_write_time(fsp, mtime);
4639 * More insanity. W2K only closes the file if writelen > 0.
4644 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4646 close_status = close_file(req, fsp, NORMAL_CLOSE);
4649 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4650 fsp->fnum, (int)numtowrite, (int)nwritten,
4651 conn->num_files_open));
4653 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4654 reply_doserror(req, ERRHRD, ERRdiskfull);
4658 if(!NT_STATUS_IS_OK(close_status)) {
4659 reply_nterror(req, close_status);
4663 reply_outbuf(req, 1, 0);
4665 SSVAL(req->outbuf,smb_vwv0,nwritten);
4669 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4672 END_PROFILE(SMBwriteclose);
4677 #define DBGC_CLASS DBGC_LOCKING
4679 /****************************************************************************
4681 ****************************************************************************/
4683 void reply_lock(struct smb_request *req)
4685 connection_struct *conn = req->conn;
4686 uint64_t count,offset;
4689 struct byte_range_lock *br_lck = NULL;
4691 START_PROFILE(SMBlock);
4694 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4695 END_PROFILE(SMBlock);
4699 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4701 if (!check_fsp(conn, req, fsp)) {
4702 END_PROFILE(SMBlock);
4706 count = (uint64_t)IVAL(req->vwv+1, 0);
4707 offset = (uint64_t)IVAL(req->vwv+3, 0);
4709 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4710 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4712 br_lck = do_lock(smbd_messaging_context(),
4719 False, /* Non-blocking lock. */
4724 TALLOC_FREE(br_lck);
4726 if (NT_STATUS_V(status)) {
4727 reply_nterror(req, status);
4728 END_PROFILE(SMBlock);
4732 reply_outbuf(req, 0, 0);
4734 END_PROFILE(SMBlock);
4738 /****************************************************************************
4740 ****************************************************************************/
4742 void reply_unlock(struct smb_request *req)
4744 connection_struct *conn = req->conn;
4745 uint64_t count,offset;
4749 START_PROFILE(SMBunlock);
4752 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4753 END_PROFILE(SMBunlock);
4757 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4759 if (!check_fsp(conn, req, fsp)) {
4760 END_PROFILE(SMBunlock);
4764 count = (uint64_t)IVAL(req->vwv+1, 0);
4765 offset = (uint64_t)IVAL(req->vwv+3, 0);
4767 status = do_unlock(smbd_messaging_context(),
4774 if (NT_STATUS_V(status)) {
4775 reply_nterror(req, status);
4776 END_PROFILE(SMBunlock);
4780 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4781 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4783 reply_outbuf(req, 0, 0);
4785 END_PROFILE(SMBunlock);
4790 #define DBGC_CLASS DBGC_ALL
4792 /****************************************************************************
4794 conn POINTER CAN BE NULL HERE !
4795 ****************************************************************************/
4797 void reply_tdis(struct smb_request *req)
4799 connection_struct *conn = req->conn;
4800 START_PROFILE(SMBtdis);
4803 DEBUG(4,("Invalid connection in tdis\n"));
4804 reply_doserror(req, ERRSRV, ERRinvnid);
4805 END_PROFILE(SMBtdis);
4811 close_cnum(conn,req->vuid);
4814 reply_outbuf(req, 0, 0);
4815 END_PROFILE(SMBtdis);
4819 /****************************************************************************
4821 conn POINTER CAN BE NULL HERE !
4822 ****************************************************************************/
4824 void reply_echo(struct smb_request *req)
4826 connection_struct *conn = req->conn;
4827 struct smb_perfcount_data local_pcd;
4828 struct smb_perfcount_data *cur_pcd;
4832 START_PROFILE(SMBecho);
4834 smb_init_perfcount_data(&local_pcd);
4837 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4838 END_PROFILE(SMBecho);
4842 smb_reverb = SVAL(req->vwv+0, 0);
4844 reply_outbuf(req, 1, req->buflen);
4846 /* copy any incoming data back out */
4847 if (req->buflen > 0) {
4848 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4851 if (smb_reverb > 100) {
4852 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4856 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4858 /* this makes sure we catch the request pcd */
4859 if (seq_num == smb_reverb) {
4860 cur_pcd = &req->pcd;
4862 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4863 cur_pcd = &local_pcd;
4866 SSVAL(req->outbuf,smb_vwv0,seq_num);
4868 show_msg((char *)req->outbuf);
4869 if (!srv_send_smb(smbd_server_fd(),
4870 (char *)req->outbuf,
4871 true, req->seqnum+1,
4872 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4874 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4877 DEBUG(3,("echo %d times\n", smb_reverb));
4879 TALLOC_FREE(req->outbuf);
4881 END_PROFILE(SMBecho);
4885 /****************************************************************************
4886 Reply to a printopen.
4887 ****************************************************************************/
4889 void reply_printopen(struct smb_request *req)
4891 connection_struct *conn = req->conn;
4893 SMB_STRUCT_STAT sbuf;
4896 START_PROFILE(SMBsplopen);
4899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4900 END_PROFILE(SMBsplopen);
4904 if (!CAN_PRINT(conn)) {
4905 reply_doserror(req, ERRDOS, ERRnoaccess);
4906 END_PROFILE(SMBsplopen);
4910 status = file_new(req, conn, &fsp);
4911 if(!NT_STATUS_IS_OK(status)) {
4912 reply_nterror(req, status);
4913 END_PROFILE(SMBsplopen);
4917 /* Open for exclusive use, write only. */
4918 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4920 if (!NT_STATUS_IS_OK(status)) {
4921 reply_nterror(req, status);
4922 END_PROFILE(SMBsplopen);
4926 reply_outbuf(req, 1, 0);
4927 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4929 DEBUG(3,("openprint fd=%d fnum=%d\n",
4930 fsp->fh->fd, fsp->fnum));
4932 END_PROFILE(SMBsplopen);
4936 /****************************************************************************
4937 Reply to a printclose.
4938 ****************************************************************************/
4940 void reply_printclose(struct smb_request *req)
4942 connection_struct *conn = req->conn;
4946 START_PROFILE(SMBsplclose);
4949 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4950 END_PROFILE(SMBsplclose);
4954 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4956 if (!check_fsp(conn, req, fsp)) {
4957 END_PROFILE(SMBsplclose);
4961 if (!CAN_PRINT(conn)) {
4962 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4963 END_PROFILE(SMBsplclose);
4967 DEBUG(3,("printclose fd=%d fnum=%d\n",
4968 fsp->fh->fd,fsp->fnum));
4970 status = close_file(req, fsp, NORMAL_CLOSE);
4972 if(!NT_STATUS_IS_OK(status)) {
4973 reply_nterror(req, status);
4974 END_PROFILE(SMBsplclose);
4978 reply_outbuf(req, 0, 0);
4980 END_PROFILE(SMBsplclose);
4984 /****************************************************************************
4985 Reply to a printqueue.
4986 ****************************************************************************/
4988 void reply_printqueue(struct smb_request *req)
4990 connection_struct *conn = req->conn;
4994 START_PROFILE(SMBsplretq);
4997 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4998 END_PROFILE(SMBsplretq);
5002 max_count = SVAL(req->vwv+0, 0);
5003 start_index = SVAL(req->vwv+1, 0);
5005 /* we used to allow the client to get the cnum wrong, but that
5006 is really quite gross and only worked when there was only
5007 one printer - I think we should now only accept it if they
5008 get it right (tridge) */
5009 if (!CAN_PRINT(conn)) {
5010 reply_doserror(req, ERRDOS, ERRnoaccess);
5011 END_PROFILE(SMBsplretq);
5015 reply_outbuf(req, 2, 3);
5016 SSVAL(req->outbuf,smb_vwv0,0);
5017 SSVAL(req->outbuf,smb_vwv1,0);
5018 SCVAL(smb_buf(req->outbuf),0,1);
5019 SSVAL(smb_buf(req->outbuf),1,0);
5021 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5022 start_index, max_count));
5025 print_queue_struct *queue = NULL;
5026 print_status_struct status;
5027 int count = print_queue_status(SNUM(conn), &queue, &status);
5028 int num_to_get = ABS(max_count);
5029 int first = (max_count>0?start_index:start_index+max_count+1);
5035 num_to_get = MIN(num_to_get,count-first);
5038 for (i=first;i<first+num_to_get;i++) {
5042 srv_put_dos_date2(p,0,queue[i].time);
5043 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5044 SSVAL(p,5, queue[i].job);
5045 SIVAL(p,7,queue[i].size);
5047 srvstr_push(blob, req->flags2, p+12,
5048 queue[i].fs_user, 16, STR_ASCII);
5050 if (message_push_blob(
5053 blob, sizeof(blob))) == -1) {
5054 reply_nterror(req, NT_STATUS_NO_MEMORY);
5055 END_PROFILE(SMBsplretq);
5061 SSVAL(req->outbuf,smb_vwv0,count);
5062 SSVAL(req->outbuf,smb_vwv1,
5063 (max_count>0?first+count:first-1));
5064 SCVAL(smb_buf(req->outbuf),0,1);
5065 SSVAL(smb_buf(req->outbuf),1,28*count);
5070 DEBUG(3,("%d entries returned in queue\n",count));
5073 END_PROFILE(SMBsplretq);
5077 /****************************************************************************
5078 Reply to a printwrite.
5079 ****************************************************************************/
5081 void reply_printwrite(struct smb_request *req)
5083 connection_struct *conn = req->conn;
5088 START_PROFILE(SMBsplwr);
5091 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5092 END_PROFILE(SMBsplwr);
5096 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5098 if (!check_fsp(conn, req, fsp)) {
5099 END_PROFILE(SMBsplwr);
5103 if (!CAN_PRINT(conn)) {
5104 reply_doserror(req, ERRDOS, ERRnoaccess);
5105 END_PROFILE(SMBsplwr);
5109 if (!CHECK_WRITE(fsp)) {
5110 reply_doserror(req, ERRDOS, ERRbadaccess);
5111 END_PROFILE(SMBsplwr);
5115 numtowrite = SVAL(req->buf, 1);
5117 if (req->buflen < numtowrite + 3) {
5118 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5119 END_PROFILE(SMBsplwr);
5123 data = (const char *)req->buf + 3;
5125 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5126 reply_unixerror(req, ERRHRD, ERRdiskfull);
5127 END_PROFILE(SMBsplwr);
5131 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5133 END_PROFILE(SMBsplwr);
5137 /****************************************************************************
5139 ****************************************************************************/
5141 void reply_mkdir(struct smb_request *req)
5143 connection_struct *conn = req->conn;
5144 char *directory = NULL;
5146 SMB_STRUCT_STAT sbuf;
5147 TALLOC_CTX *ctx = talloc_tos();
5149 START_PROFILE(SMBmkdir);
5151 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5152 STR_TERMINATE, &status);
5153 if (!NT_STATUS_IS_OK(status)) {
5154 reply_nterror(req, status);
5155 END_PROFILE(SMBmkdir);
5159 status = resolve_dfspath(ctx, conn,
5160 req->flags2 & FLAGS2_DFS_PATHNAMES,
5163 if (!NT_STATUS_IS_OK(status)) {
5164 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5165 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5166 ERRSRV, ERRbadpath);
5167 END_PROFILE(SMBmkdir);
5170 reply_nterror(req, status);
5171 END_PROFILE(SMBmkdir);
5175 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
5176 if (!NT_STATUS_IS_OK(status)) {
5177 reply_nterror(req, status);
5178 END_PROFILE(SMBmkdir);
5182 status = check_name(conn, directory);
5183 if (!NT_STATUS_IS_OK(status)) {
5184 reply_nterror(req, status);
5185 END_PROFILE(SMBmkdir);
5189 status = create_directory(conn, req, directory);
5191 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5193 if (!NT_STATUS_IS_OK(status)) {
5195 if (!use_nt_status()
5196 && NT_STATUS_EQUAL(status,
5197 NT_STATUS_OBJECT_NAME_COLLISION)) {
5199 * Yes, in the DOS error code case we get a
5200 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5201 * samba4 torture test.
5203 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5206 reply_nterror(req, status);
5207 END_PROFILE(SMBmkdir);
5211 reply_outbuf(req, 0, 0);
5213 DEBUG( 3, ( "mkdir %s\n", directory ) );
5215 END_PROFILE(SMBmkdir);
5219 /****************************************************************************
5220 Static function used by reply_rmdir to delete an entire directory
5221 tree recursively. Return True on ok, False on fail.
5222 ****************************************************************************/
5224 static bool recursive_rmdir(TALLOC_CTX *ctx,
5225 connection_struct *conn,
5228 const char *dname = NULL;
5232 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5238 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5239 char *fullname = NULL;
5241 if (ISDOT(dname) || ISDOTDOT(dname)) {
5245 if (!is_visible_file(conn, directory, dname, &st, False)) {
5249 /* Construct the full name. */
5250 fullname = talloc_asprintf(ctx,
5260 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5265 if(st.st_mode & S_IFDIR) {
5266 if(!recursive_rmdir(ctx, conn, fullname)) {
5270 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5274 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5278 TALLOC_FREE(fullname);
5280 TALLOC_FREE(dir_hnd);
5284 /****************************************************************************
5285 The internals of the rmdir code - called elsewhere.
5286 ****************************************************************************/
5288 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5289 connection_struct *conn,
5290 const char *directory)
5295 /* Might be a symlink. */
5296 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5297 return map_nt_error_from_unix(errno);
5300 if (S_ISLNK(st.st_mode)) {
5301 /* Is what it points to a directory ? */
5302 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5303 return map_nt_error_from_unix(errno);
5305 if (!(S_ISDIR(st.st_mode))) {
5306 return NT_STATUS_NOT_A_DIRECTORY;
5308 ret = SMB_VFS_UNLINK(conn,directory);
5310 ret = SMB_VFS_RMDIR(conn,directory);
5313 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5314 FILE_NOTIFY_CHANGE_DIR_NAME,
5316 return NT_STATUS_OK;
5319 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5321 * Check to see if the only thing in this directory are
5322 * vetoed files/directories. If so then delete them and
5323 * retry. If we fail to delete any of them (and we *don't*
5324 * do a recursive delete) then fail the rmdir.
5328 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5329 directory, NULL, 0);
5331 if(dir_hnd == NULL) {
5336 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5337 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5339 if (!is_visible_file(conn, directory, dname, &st, False))
5341 if(!IS_VETO_PATH(conn, dname)) {
5342 TALLOC_FREE(dir_hnd);
5348 /* We only have veto files/directories.
5349 * Are we allowed to delete them ? */
5351 if(!lp_recursive_veto_delete(SNUM(conn))) {
5352 TALLOC_FREE(dir_hnd);
5357 /* Do a recursive delete. */
5358 RewindDir(dir_hnd,&dirpos);
5359 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5360 char *fullname = NULL;
5362 if (ISDOT(dname) || ISDOTDOT(dname)) {
5365 if (!is_visible_file(conn, directory, dname, &st, False)) {
5369 fullname = talloc_asprintf(ctx,
5379 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5382 if(st.st_mode & S_IFDIR) {
5383 if(!recursive_rmdir(ctx, conn, fullname)) {
5386 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5389 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5392 TALLOC_FREE(fullname);
5394 TALLOC_FREE(dir_hnd);
5395 /* Retry the rmdir */
5396 ret = SMB_VFS_RMDIR(conn,directory);
5402 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5403 "%s\n", directory,strerror(errno)));
5404 return map_nt_error_from_unix(errno);
5407 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5408 FILE_NOTIFY_CHANGE_DIR_NAME,
5411 return NT_STATUS_OK;
5414 /****************************************************************************
5416 ****************************************************************************/
5418 void reply_rmdir(struct smb_request *req)
5420 connection_struct *conn = req->conn;
5421 char *directory = NULL;
5422 SMB_STRUCT_STAT sbuf;
5424 TALLOC_CTX *ctx = talloc_tos();
5426 START_PROFILE(SMBrmdir);
5428 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5429 STR_TERMINATE, &status);
5430 if (!NT_STATUS_IS_OK(status)) {
5431 reply_nterror(req, status);
5432 END_PROFILE(SMBrmdir);
5436 status = resolve_dfspath(ctx, conn,
5437 req->flags2 & FLAGS2_DFS_PATHNAMES,
5440 if (!NT_STATUS_IS_OK(status)) {
5441 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5442 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5443 ERRSRV, ERRbadpath);
5444 END_PROFILE(SMBrmdir);
5447 reply_nterror(req, status);
5448 END_PROFILE(SMBrmdir);
5452 status = unix_convert(ctx, conn, directory, False, &directory,
5454 if (!NT_STATUS_IS_OK(status)) {
5455 reply_nterror(req, status);
5456 END_PROFILE(SMBrmdir);
5460 status = check_name(conn, directory);
5461 if (!NT_STATUS_IS_OK(status)) {
5462 reply_nterror(req, status);
5463 END_PROFILE(SMBrmdir);
5467 dptr_closepath(directory, req->smbpid);
5468 status = rmdir_internals(ctx, conn, directory);
5469 if (!NT_STATUS_IS_OK(status)) {
5470 reply_nterror(req, status);
5471 END_PROFILE(SMBrmdir);
5475 reply_outbuf(req, 0, 0);
5477 DEBUG( 3, ( "rmdir %s\n", directory ) );
5479 END_PROFILE(SMBrmdir);
5483 /*******************************************************************
5484 Resolve wildcards in a filename rename.
5485 ********************************************************************/
5487 static bool resolve_wildcards(TALLOC_CTX *ctx,
5492 char *name2_copy = NULL;
5497 char *p,*p2, *pname1, *pname2;
5499 name2_copy = talloc_strdup(ctx, name2);
5504 pname1 = strrchr_m(name1,'/');
5505 pname2 = strrchr_m(name2_copy,'/');
5507 if (!pname1 || !pname2) {
5511 /* Truncate the copy of name2 at the last '/' */
5514 /* Now go past the '/' */
5518 root1 = talloc_strdup(ctx, pname1);
5519 root2 = talloc_strdup(ctx, pname2);
5521 if (!root1 || !root2) {
5525 p = strrchr_m(root1,'.');
5528 ext1 = talloc_strdup(ctx, p+1);
5530 ext1 = talloc_strdup(ctx, "");
5532 p = strrchr_m(root2,'.');
5535 ext2 = talloc_strdup(ctx, p+1);
5537 ext2 = talloc_strdup(ctx, "");
5540 if (!ext1 || !ext2) {
5548 /* Hmmm. Should this be mb-aware ? */
5551 } else if (*p2 == '*') {
5553 root2 = talloc_asprintf(ctx, "%s%s",
5572 /* Hmmm. Should this be mb-aware ? */
5575 } else if (*p2 == '*') {
5577 ext2 = talloc_asprintf(ctx, "%s%s",
5593 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5598 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5610 /****************************************************************************
5611 Ensure open files have their names updated. Updated to notify other smbd's
5613 ****************************************************************************/
5615 static void rename_open_files(connection_struct *conn,
5616 struct share_mode_lock *lck,
5617 const char *newname)
5620 bool did_rename = False;
5622 for(fsp = file_find_di_first(lck->id); fsp;
5623 fsp = file_find_di_next(fsp)) {
5624 /* fsp_name is a relative path under the fsp. To change this for other
5625 sharepaths we need to manipulate relative paths. */
5626 /* TODO - create the absolute path and manipulate the newname
5627 relative to the sharepath. */
5628 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5631 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5632 fsp->fnum, file_id_string_tos(&fsp->file_id),
5633 fsp->fsp_name, newname ));
5634 string_set(&fsp->fsp_name, newname);
5639 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5640 file_id_string_tos(&lck->id), newname ));
5643 /* Send messages to all smbd's (not ourself) that the name has changed. */
5644 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5648 /****************************************************************************
5649 We need to check if the source path is a parent directory of the destination
5650 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5651 refuse the rename with a sharing violation. Under UNIX the above call can
5652 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5653 probably need to check that the client is a Windows one before disallowing
5654 this as a UNIX client (one with UNIX extensions) can know the source is a
5655 symlink and make this decision intelligently. Found by an excellent bug
5656 report from <AndyLiebman@aol.com>.
5657 ****************************************************************************/
5659 static bool rename_path_prefix_equal(const char *src, const char *dest)
5661 const char *psrc = src;
5662 const char *pdst = dest;
5665 if (psrc[0] == '.' && psrc[1] == '/') {
5668 if (pdst[0] == '.' && pdst[1] == '/') {
5671 if ((slen = strlen(psrc)) > strlen(pdst)) {
5674 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5678 * Do the notify calls from a rename
5681 static void notify_rename(connection_struct *conn, bool is_dir,
5682 const char *oldpath, const char *newpath)
5684 char *olddir, *newdir;
5685 const char *oldname, *newname;
5688 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5689 : FILE_NOTIFY_CHANGE_FILE_NAME;
5691 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5692 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5693 TALLOC_FREE(olddir);
5697 if (strcmp(olddir, newdir) == 0) {
5698 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5699 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5702 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5703 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5705 TALLOC_FREE(olddir);
5706 TALLOC_FREE(newdir);
5708 /* this is a strange one. w2k3 gives an additional event for
5709 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5710 files, but not directories */
5712 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5713 FILE_NOTIFY_CHANGE_ATTRIBUTES
5714 |FILE_NOTIFY_CHANGE_CREATION,
5719 /****************************************************************************
5720 Rename an open file - given an fsp.
5721 ****************************************************************************/
5723 NTSTATUS rename_internals_fsp(connection_struct *conn,
5726 const char *newname_last_component,
5728 bool replace_if_exists)
5730 TALLOC_CTX *ctx = talloc_tos();
5731 SMB_STRUCT_STAT sbuf, sbuf1;
5732 NTSTATUS status = NT_STATUS_OK;
5733 struct share_mode_lock *lck = NULL;
5734 bool dst_exists, old_is_stream, new_is_stream;
5738 status = check_name(conn, newname);
5739 if (!NT_STATUS_IS_OK(status)) {
5743 /* Ensure newname contains a '/' */
5744 if(strrchr_m(newname,'/') == 0) {
5745 newname = talloc_asprintf(ctx,
5749 return NT_STATUS_NO_MEMORY;
5754 * Check for special case with case preserving and not
5755 * case sensitive. If the old last component differs from the original
5756 * last component only by case, then we should allow
5757 * the rename (user is trying to change the case of the
5761 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5762 strequal(newname, fsp->fsp_name)) {
5764 char *newname_modified_last_component = NULL;
5767 * Get the last component of the modified name.
5768 * Note that we guarantee that newname contains a '/'
5771 p = strrchr_m(newname,'/');
5772 newname_modified_last_component = talloc_strdup(ctx,
5774 if (!newname_modified_last_component) {
5775 return NT_STATUS_NO_MEMORY;
5778 if(strcsequal(newname_modified_last_component,
5779 newname_last_component) == False) {
5781 * Replace the modified last component with
5784 *p = '\0'; /* Truncate at the '/' */
5785 newname = talloc_asprintf(ctx,
5788 newname_last_component);
5793 * If the src and dest names are identical - including case,
5794 * don't do the rename, just return success.
5797 if (strcsequal(fsp->fsp_name, newname)) {
5798 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5800 return NT_STATUS_OK;
5803 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5804 new_is_stream = is_ntfs_stream_name(newname);
5806 /* Return the correct error code if both names aren't streams. */
5807 if (!old_is_stream && new_is_stream) {
5808 return NT_STATUS_OBJECT_NAME_INVALID;
5811 if (old_is_stream && !new_is_stream) {
5812 return NT_STATUS_INVALID_PARAMETER;
5816 * Have vfs_object_exist also fill sbuf1
5818 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5820 if(!replace_if_exists && dst_exists) {
5821 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5822 fsp->fsp_name,newname));
5823 return NT_STATUS_OBJECT_NAME_COLLISION;
5827 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5828 files_struct *dst_fsp = file_find_di_first(fileid);
5829 /* The file can be open when renaming a stream */
5830 if (dst_fsp && !new_is_stream) {
5831 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5832 return NT_STATUS_ACCESS_DENIED;
5836 /* Ensure we have a valid stat struct for the source. */
5837 if (fsp->fh->fd != -1) {
5838 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5839 return map_nt_error_from_unix(errno);
5843 if (fsp->posix_open) {
5844 ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
5846 ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
5849 return map_nt_error_from_unix(errno);
5853 status = can_rename(conn, fsp, attrs, &sbuf);
5855 if (!NT_STATUS_IS_OK(status)) {
5856 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5857 nt_errstr(status), fsp->fsp_name,newname));
5858 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5859 status = NT_STATUS_ACCESS_DENIED;
5863 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5864 return NT_STATUS_ACCESS_DENIED;
5867 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5871 * We have the file open ourselves, so not being able to get the
5872 * corresponding share mode lock is a fatal error.
5875 SMB_ASSERT(lck != NULL);
5877 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5878 uint32 create_options = fsp->fh->private_options;
5880 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5881 fsp->fsp_name,newname));
5883 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5885 rename_open_files(conn, lck, newname);
5888 * A rename acts as a new file create w.r.t. allowing an initial delete
5889 * on close, probably because in Windows there is a new handle to the
5890 * new file. If initial delete on close was requested but not
5891 * originally set, we need to set it here. This is probably not 100% correct,
5892 * but will work for the CIFSFS client which in non-posix mode
5893 * depends on these semantics. JRA.
5896 if (create_options & FILE_DELETE_ON_CLOSE) {
5897 status = can_set_delete_on_close(fsp, True, 0);
5899 if (NT_STATUS_IS_OK(status)) {
5900 /* Note that here we set the *inital* delete on close flag,
5901 * not the regular one. The magic gets handled in close. */
5902 fsp->initial_delete_on_close = True;
5906 return NT_STATUS_OK;
5911 if (errno == ENOTDIR || errno == EISDIR) {
5912 status = NT_STATUS_OBJECT_NAME_COLLISION;
5914 status = map_nt_error_from_unix(errno);
5917 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5918 nt_errstr(status), fsp->fsp_name,newname));
5923 /****************************************************************************
5924 The guts of the rename command, split out so it may be called by the NT SMB
5926 ****************************************************************************/
5928 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5929 connection_struct *conn,
5930 struct smb_request *req,
5931 const char *name_in,
5932 const char *newname_in,
5934 bool replace_if_exists,
5937 uint32_t access_mask)
5939 char *directory = NULL;
5941 char *last_component_src = NULL;
5942 char *last_component_dest = NULL;
5944 char *newname = NULL;
5947 NTSTATUS status = NT_STATUS_OK;
5948 SMB_STRUCT_STAT sbuf1, sbuf2;
5949 struct smb_Dir *dir_hnd = NULL;
5952 int create_options = 0;
5953 bool posix_pathnames = lp_posix_pathnames();
5958 status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5959 &last_component_src, &sbuf1);
5960 if (!NT_STATUS_IS_OK(status)) {
5964 status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5965 &last_component_dest, &sbuf2);
5966 if (!NT_STATUS_IS_OK(status)) {
5971 * Split the old name into directory and last component
5972 * strings. Note that unix_convert may have stripped off a
5973 * leading ./ from both name and newname if the rename is
5974 * at the root of the share. We need to make sure either both
5975 * name and newname contain a / character or neither of them do
5976 * as this is checked in resolve_wildcards().
5979 p = strrchr_m(name,'/');
5981 directory = talloc_strdup(ctx, ".");
5983 return NT_STATUS_NO_MEMORY;
5988 directory = talloc_strdup(ctx, name);
5990 return NT_STATUS_NO_MEMORY;
5993 *p = '/'; /* Replace needed for exceptional test below. */
5997 * We should only check the mangled cache
5998 * here if unix_convert failed. This means
5999 * that the path in 'mask' doesn't exist
6000 * on the file system and so we need to look
6001 * for a possible mangle. This patch from
6002 * Tine Smukavec <valentin.smukavec@hermes.si>.
6005 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6006 char *new_mask = NULL;
6007 mangle_lookup_name_from_8_3(ctx,
6016 if (!src_has_wild) {
6020 * No wildcards - just process the one file.
6022 /* Add a terminating '/' to the directory name. */
6023 directory = talloc_asprintf_append(directory,
6027 return NT_STATUS_NO_MEMORY;
6030 /* Ensure newname contains a '/' also */
6031 if(strrchr_m(newname,'/') == 0) {
6032 newname = talloc_asprintf(ctx,
6036 return NT_STATUS_NO_MEMORY;
6040 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6041 "case_preserve = %d, short case preserve = %d, "
6042 "directory = %s, newname = %s, "
6043 "last_component_dest = %s\n",
6044 conn->case_sensitive, conn->case_preserve,
6045 conn->short_case_preserve, directory,
6046 newname, last_component_dest));
6048 /* The dest name still may have wildcards. */
6049 if (dest_has_wild) {
6050 char *mod_newname = NULL;
6051 if (!resolve_wildcards(ctx,
6052 directory,newname,&mod_newname)) {
6053 DEBUG(6, ("rename_internals: resolve_wildcards "
6057 return NT_STATUS_NO_MEMORY;
6059 newname = mod_newname;
6063 if (posix_pathnames) {
6064 SMB_VFS_LSTAT(conn, directory, &sbuf1);
6066 SMB_VFS_STAT(conn, directory, &sbuf1);
6069 if (S_ISDIR(sbuf1.st_mode)) {
6070 create_options |= FILE_DIRECTORY_FILE;
6073 status = SMB_VFS_CREATE_FILE(
6076 0, /* root_dir_fid */
6077 directory, /* fname */
6078 0, /* create_file_flags */
6079 access_mask, /* access_mask */
6080 (FILE_SHARE_READ | /* share_access */
6082 FILE_OPEN, /* create_disposition*/
6083 create_options, /* create_options */
6084 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6085 0, /* oplock_request */
6086 0, /* allocation_size */
6091 &sbuf1); /* psbuf */
6093 if (!NT_STATUS_IS_OK(status)) {
6094 DEBUG(3, ("Could not open rename source %s: %s\n",
6095 directory, nt_errstr(status)));
6099 status = rename_internals_fsp(conn, fsp, newname,
6100 last_component_dest,
6101 attrs, replace_if_exists);
6103 close_file(req, fsp, NORMAL_CLOSE);
6105 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6106 nt_errstr(status), directory,newname));
6112 * Wildcards - process each file that matches.
6114 if (strequal(mask,"????????.???")) {
6119 status = check_name(conn, directory);
6120 if (!NT_STATUS_IS_OK(status)) {
6124 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
6125 if (dir_hnd == NULL) {
6126 return map_nt_error_from_unix(errno);
6129 status = NT_STATUS_NO_SUCH_FILE;
6131 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6132 * - gentest fix. JRA
6135 while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
6136 files_struct *fsp = NULL;
6138 char *destname = NULL;
6139 bool sysdir_entry = False;
6141 /* Quick check for "." and ".." */
6142 if (ISDOT(dname) || ISDOTDOT(dname)) {
6144 sysdir_entry = True;
6150 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6154 if(!mask_match(dname, mask, conn->case_sensitive)) {
6159 status = NT_STATUS_OBJECT_NAME_INVALID;
6163 fname = talloc_asprintf(ctx,
6168 return NT_STATUS_NO_MEMORY;
6171 if (!resolve_wildcards(ctx,
6172 fname,newname,&destname)) {
6173 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6179 return NT_STATUS_NO_MEMORY;
6183 if (posix_pathnames) {
6184 SMB_VFS_LSTAT(conn, fname, &sbuf1);
6186 SMB_VFS_STAT(conn, fname, &sbuf1);
6191 if (S_ISDIR(sbuf1.st_mode)) {
6192 create_options |= FILE_DIRECTORY_FILE;
6195 status = SMB_VFS_CREATE_FILE(
6198 0, /* root_dir_fid */
6200 0, /* create_file_flags */
6201 access_mask, /* access_mask */
6202 (FILE_SHARE_READ | /* share_access */
6204 FILE_OPEN, /* create_disposition*/
6205 create_options, /* create_options */
6206 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6207 0, /* oplock_request */
6208 0, /* allocation_size */
6213 &sbuf1); /* psbuf */
6215 if (!NT_STATUS_IS_OK(status)) {
6216 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6217 "returned %s rename %s -> %s\n",
6218 nt_errstr(status), directory, newname));
6222 status = rename_internals_fsp(conn, fsp, destname, dname,
6223 attrs, replace_if_exists);
6225 close_file(req, fsp, NORMAL_CLOSE);
6227 if (!NT_STATUS_IS_OK(status)) {
6228 DEBUG(3, ("rename_internals_fsp returned %s for "
6229 "rename %s -> %s\n", nt_errstr(status),
6230 directory, newname));
6236 DEBUG(3,("rename_internals: doing rename on %s -> "
6237 "%s\n",fname,destname));
6240 TALLOC_FREE(destname);
6242 TALLOC_FREE(dir_hnd);
6244 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6245 status = map_nt_error_from_unix(errno);
6251 /****************************************************************************
6253 ****************************************************************************/
6255 void reply_mv(struct smb_request *req)
6257 connection_struct *conn = req->conn;
6259 char *newname = NULL;
6263 bool src_has_wcard = False;
6264 bool dest_has_wcard = False;
6265 TALLOC_CTX *ctx = talloc_tos();
6267 START_PROFILE(SMBmv);
6270 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6275 attrs = SVAL(req->vwv+0, 0);
6277 p = (const char *)req->buf + 1;
6278 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6279 &status, &src_has_wcard);
6280 if (!NT_STATUS_IS_OK(status)) {
6281 reply_nterror(req, status);
6286 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6287 &status, &dest_has_wcard);
6288 if (!NT_STATUS_IS_OK(status)) {
6289 reply_nterror(req, status);
6294 status = resolve_dfspath_wcard(ctx, conn,
6295 req->flags2 & FLAGS2_DFS_PATHNAMES,
6299 if (!NT_STATUS_IS_OK(status)) {
6300 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6301 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6302 ERRSRV, ERRbadpath);
6306 reply_nterror(req, status);
6311 status = resolve_dfspath_wcard(ctx, conn,
6312 req->flags2 & FLAGS2_DFS_PATHNAMES,
6316 if (!NT_STATUS_IS_OK(status)) {
6317 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6318 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6319 ERRSRV, ERRbadpath);
6323 reply_nterror(req, status);
6328 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6330 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6331 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6332 if (!NT_STATUS_IS_OK(status)) {
6333 if (open_was_deferred(req->mid)) {
6334 /* We have re-scheduled this call. */
6338 reply_nterror(req, status);
6343 reply_outbuf(req, 0, 0);
6349 /*******************************************************************
6350 Copy a file as part of a reply_copy.
6351 ******************************************************************/
6354 * TODO: check error codes on all callers
6357 NTSTATUS copy_file(TALLOC_CTX *ctx,
6358 connection_struct *conn,
6363 bool target_is_directory)
6365 SMB_STRUCT_STAT src_sbuf, sbuf2;
6367 files_struct *fsp1,*fsp2;
6370 uint32 new_create_disposition;
6373 dest = talloc_strdup(ctx, dest1);
6375 return NT_STATUS_NO_MEMORY;
6377 if (target_is_directory) {
6378 const char *p = strrchr_m(src,'/');
6384 dest = talloc_asprintf_append(dest,
6388 return NT_STATUS_NO_MEMORY;
6392 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6394 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6397 if (!target_is_directory && count) {
6398 new_create_disposition = FILE_OPEN;
6400 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6401 NULL, NULL, &new_create_disposition, NULL)) {
6403 return NT_STATUS_INVALID_PARAMETER;
6407 status = SMB_VFS_CREATE_FILE(
6410 0, /* root_dir_fid */
6412 0, /* create_file_flags */
6413 FILE_GENERIC_READ, /* access_mask */
6414 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6415 FILE_OPEN, /* create_disposition*/
6416 0, /* create_options */
6417 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6418 INTERNAL_OPEN_ONLY, /* oplock_request */
6419 0, /* allocation_size */
6424 &src_sbuf); /* psbuf */
6426 if (!NT_STATUS_IS_OK(status)) {
6431 dosattrs = dos_mode(conn, src, &src_sbuf);
6432 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6433 ZERO_STRUCTP(&sbuf2);
6436 status = SMB_VFS_CREATE_FILE(
6439 0, /* root_dir_fid */
6441 0, /* create_file_flags */
6442 FILE_GENERIC_WRITE, /* access_mask */
6443 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6444 new_create_disposition, /* create_disposition*/
6445 0, /* create_options */
6446 dosattrs, /* file_attributes */
6447 INTERNAL_OPEN_ONLY, /* oplock_request */
6448 0, /* allocation_size */
6453 &sbuf2); /* psbuf */
6457 if (!NT_STATUS_IS_OK(status)) {
6458 close_file(NULL, fsp1, ERROR_CLOSE);
6462 if ((ofun&3) == 1) {
6463 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6464 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6466 * Stop the copy from occurring.
6469 src_sbuf.st_size = 0;
6473 if (src_sbuf.st_size) {
6474 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6477 close_file(NULL, fsp1, NORMAL_CLOSE);
6479 /* Ensure the modtime is set correctly on the destination file. */
6480 set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
6483 * As we are opening fsp1 read-only we only expect
6484 * an error on close on fsp2 if we are out of space.
6485 * Thus we don't look at the error return from the
6488 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6490 if (!NT_STATUS_IS_OK(status)) {
6494 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6495 return NT_STATUS_DISK_FULL;
6498 return NT_STATUS_OK;
6501 /****************************************************************************
6502 Reply to a file copy.
6503 ****************************************************************************/
6505 void reply_copy(struct smb_request *req)
6507 connection_struct *conn = req->conn;
6509 char *newname = NULL;
6510 char *directory = NULL;
6511 const char *mask = NULL;
6512 const char mask_star[] = "*";
6515 int error = ERRnoaccess;
6520 bool target_is_directory=False;
6521 bool source_has_wild = False;
6522 bool dest_has_wild = False;
6523 SMB_STRUCT_STAT sbuf1, sbuf2;
6525 TALLOC_CTX *ctx = talloc_tos();
6527 START_PROFILE(SMBcopy);
6530 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6531 END_PROFILE(SMBcopy);
6535 tid2 = SVAL(req->vwv+0, 0);
6536 ofun = SVAL(req->vwv+1, 0);
6537 flags = SVAL(req->vwv+2, 0);
6539 p = (const char *)req->buf;
6540 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6541 &status, &source_has_wild);
6542 if (!NT_STATUS_IS_OK(status)) {
6543 reply_nterror(req, status);
6544 END_PROFILE(SMBcopy);
6547 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6548 &status, &dest_has_wild);
6549 if (!NT_STATUS_IS_OK(status)) {
6550 reply_nterror(req, status);
6551 END_PROFILE(SMBcopy);
6555 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6557 if (tid2 != conn->cnum) {
6558 /* can't currently handle inter share copies XXXX */
6559 DEBUG(3,("Rejecting inter-share copy\n"));
6560 reply_doserror(req, ERRSRV, ERRinvdevice);
6561 END_PROFILE(SMBcopy);
6565 status = resolve_dfspath_wcard(ctx, conn,
6566 req->flags2 & FLAGS2_DFS_PATHNAMES,
6570 if (!NT_STATUS_IS_OK(status)) {
6571 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6572 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6573 ERRSRV, ERRbadpath);
6574 END_PROFILE(SMBcopy);
6577 reply_nterror(req, status);
6578 END_PROFILE(SMBcopy);
6582 status = resolve_dfspath_wcard(ctx, conn,
6583 req->flags2 & FLAGS2_DFS_PATHNAMES,
6587 if (!NT_STATUS_IS_OK(status)) {
6588 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6589 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6590 ERRSRV, ERRbadpath);
6591 END_PROFILE(SMBcopy);
6594 reply_nterror(req, status);
6595 END_PROFILE(SMBcopy);
6599 status = unix_convert(ctx, conn, name, source_has_wild,
6600 &name, NULL, &sbuf1);
6601 if (!NT_STATUS_IS_OK(status)) {
6602 reply_nterror(req, status);
6603 END_PROFILE(SMBcopy);
6607 status = unix_convert(ctx, conn, newname, dest_has_wild,
6608 &newname, NULL, &sbuf2);
6609 if (!NT_STATUS_IS_OK(status)) {
6610 reply_nterror(req, status);
6611 END_PROFILE(SMBcopy);
6615 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6617 if ((flags&1) && target_is_directory) {
6618 reply_doserror(req, ERRDOS, ERRbadfile);
6619 END_PROFILE(SMBcopy);
6623 if ((flags&2) && !target_is_directory) {
6624 reply_doserror(req, ERRDOS, ERRbadpath);
6625 END_PROFILE(SMBcopy);
6629 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6630 /* wants a tree copy! XXXX */
6631 DEBUG(3,("Rejecting tree copy\n"));
6632 reply_doserror(req, ERRSRV, ERRerror);
6633 END_PROFILE(SMBcopy);
6637 p = strrchr_m(name,'/');
6639 directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
6642 directory = talloc_strdup(ctx, "./");
6647 reply_nterror(req, NT_STATUS_NO_MEMORY);
6648 END_PROFILE(SMBcopy);
6653 * We should only check the mangled cache
6654 * here if unix_convert failed. This means
6655 * that the path in 'mask' doesn't exist
6656 * on the file system and so we need to look
6657 * for a possible mangle. This patch from
6658 * Tine Smukavec <valentin.smukavec@hermes.si>.
6661 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6662 char *new_mask = NULL;
6663 mangle_lookup_name_from_8_3(ctx,
6672 if (!source_has_wild) {
6673 directory = talloc_asprintf_append(directory,
6676 if (dest_has_wild) {
6677 char *mod_newname = NULL;
6678 if (!resolve_wildcards(ctx,
6679 directory,newname,&mod_newname)) {
6680 reply_nterror(req, NT_STATUS_NO_MEMORY);
6681 END_PROFILE(SMBcopy);
6684 newname = mod_newname;
6687 status = check_name(conn, directory);
6688 if (!NT_STATUS_IS_OK(status)) {
6689 reply_nterror(req, status);
6690 END_PROFILE(SMBcopy);
6694 status = check_name(conn, newname);
6695 if (!NT_STATUS_IS_OK(status)) {
6696 reply_nterror(req, status);
6697 END_PROFILE(SMBcopy);
6701 status = copy_file(ctx,conn,directory,newname,ofun,
6702 count,target_is_directory);
6704 if(!NT_STATUS_IS_OK(status)) {
6705 reply_nterror(req, status);
6706 END_PROFILE(SMBcopy);
6712 struct smb_Dir *dir_hnd = NULL;
6713 const char *dname = NULL;
6716 if (strequal(mask,"????????.???")) {
6720 status = check_name(conn, directory);
6721 if (!NT_STATUS_IS_OK(status)) {
6722 reply_nterror(req, status);
6723 END_PROFILE(SMBcopy);
6727 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6728 if (dir_hnd == NULL) {
6729 status = map_nt_error_from_unix(errno);
6730 reply_nterror(req, status);
6731 END_PROFILE(SMBcopy);
6737 while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
6738 char *destname = NULL;
6741 if (ISDOT(dname) || ISDOTDOT(dname)) {
6745 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6749 if(!mask_match(dname, mask, conn->case_sensitive)) {
6753 error = ERRnoaccess;
6754 fname = talloc_asprintf(ctx,
6759 TALLOC_FREE(dir_hnd);
6760 reply_nterror(req, NT_STATUS_NO_MEMORY);
6761 END_PROFILE(SMBcopy);
6765 if (!resolve_wildcards(ctx,
6766 fname,newname,&destname)) {
6770 TALLOC_FREE(dir_hnd);
6771 reply_nterror(req, NT_STATUS_NO_MEMORY);
6772 END_PROFILE(SMBcopy);
6776 status = check_name(conn, fname);
6777 if (!NT_STATUS_IS_OK(status)) {
6778 TALLOC_FREE(dir_hnd);
6779 reply_nterror(req, status);
6780 END_PROFILE(SMBcopy);
6784 status = check_name(conn, destname);
6785 if (!NT_STATUS_IS_OK(status)) {
6786 TALLOC_FREE(dir_hnd);
6787 reply_nterror(req, status);
6788 END_PROFILE(SMBcopy);
6792 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6794 status = copy_file(ctx,conn,fname,destname,ofun,
6795 count,target_is_directory);
6796 if (NT_STATUS_IS_OK(status)) {
6800 TALLOC_FREE(destname);
6802 TALLOC_FREE(dir_hnd);
6807 /* Error on close... */
6809 reply_unixerror(req, ERRHRD, ERRgeneral);
6810 END_PROFILE(SMBcopy);
6814 reply_doserror(req, ERRDOS, error);
6815 END_PROFILE(SMBcopy);
6819 reply_outbuf(req, 1, 0);
6820 SSVAL(req->outbuf,smb_vwv0,count);
6822 END_PROFILE(SMBcopy);
6827 #define DBGC_CLASS DBGC_LOCKING
6829 /****************************************************************************
6830 Get a lock pid, dealing with large count requests.
6831 ****************************************************************************/
6833 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6834 bool large_file_format)
6836 if(!large_file_format)
6837 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6839 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6842 /****************************************************************************
6843 Get a lock count, dealing with large count requests.
6844 ****************************************************************************/
6846 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6847 bool large_file_format)
6851 if(!large_file_format) {
6852 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6855 #if defined(HAVE_LONGLONG)
6856 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6857 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6858 #else /* HAVE_LONGLONG */
6861 * NT4.x seems to be broken in that it sends large file (64 bit)
6862 * lockingX calls even if the CAP_LARGE_FILES was *not*
6863 * negotiated. For boxes without large unsigned ints truncate the
6864 * lock count by dropping the top 32 bits.
6867 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6868 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6869 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6870 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6871 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6874 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6875 #endif /* HAVE_LONGLONG */
6881 #if !defined(HAVE_LONGLONG)
6882 /****************************************************************************
6883 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6884 ****************************************************************************/
6886 static uint32 map_lock_offset(uint32 high, uint32 low)
6890 uint32 highcopy = high;
6893 * Try and find out how many significant bits there are in high.
6896 for(i = 0; highcopy; i++)
6900 * We use 31 bits not 32 here as POSIX
6901 * lock offsets may not be negative.
6904 mask = (~0) << (31 - i);
6907 return 0; /* Fail. */
6913 #endif /* !defined(HAVE_LONGLONG) */
6915 /****************************************************************************
6916 Get a lock offset, dealing with large offset requests.
6917 ****************************************************************************/
6919 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6920 bool large_file_format, bool *err)
6922 uint64_t offset = 0;
6926 if(!large_file_format) {
6927 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6930 #if defined(HAVE_LONGLONG)
6931 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6932 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6933 #else /* HAVE_LONGLONG */
6936 * NT4.x seems to be broken in that it sends large file (64 bit)
6937 * lockingX calls even if the CAP_LARGE_FILES was *not*
6938 * negotiated. For boxes without large unsigned ints mangle the
6939 * lock offset by mapping the top 32 bits onto the lower 32.
6942 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6943 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6944 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6947 if((new_low = map_lock_offset(high, low)) == 0) {
6949 return (uint64_t)-1;
6952 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6953 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6954 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6955 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6958 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6959 #endif /* HAVE_LONGLONG */
6965 /****************************************************************************
6966 Reply to a lockingX request.
6967 ****************************************************************************/
6969 void reply_lockingX(struct smb_request *req)
6971 connection_struct *conn = req->conn;
6973 unsigned char locktype;
6974 unsigned char oplocklevel;
6977 uint64_t count = 0, offset = 0;
6981 const uint8_t *data;
6982 bool large_file_format;
6984 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6986 START_PROFILE(SMBlockingX);
6989 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6990 END_PROFILE(SMBlockingX);
6994 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
6995 locktype = CVAL(req->vwv+3, 0);
6996 oplocklevel = CVAL(req->vwv+3, 1);
6997 num_ulocks = SVAL(req->vwv+6, 0);
6998 num_locks = SVAL(req->vwv+7, 0);
6999 lock_timeout = IVAL(req->vwv+4, 0);
7000 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7002 if (!check_fsp(conn, req, fsp)) {
7003 END_PROFILE(SMBlockingX);
7009 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7010 /* we don't support these - and CANCEL_LOCK makes w2k
7011 and XP reboot so I don't really want to be
7012 compatible! (tridge) */
7013 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7014 END_PROFILE(SMBlockingX);
7018 /* Check if this is an oplock break on a file
7019 we have granted an oplock on.
7021 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7022 /* Client can insist on breaking to none. */
7023 bool break_to_none = (oplocklevel == 0);
7026 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7027 "for fnum = %d\n", (unsigned int)oplocklevel,
7031 * Make sure we have granted an exclusive or batch oplock on
7035 if (fsp->oplock_type == 0) {
7037 /* The Samba4 nbench simulator doesn't understand
7038 the difference between break to level2 and break
7039 to none from level2 - it sends oplock break
7040 replies in both cases. Don't keep logging an error
7041 message here - just ignore it. JRA. */
7043 DEBUG(5,("reply_lockingX: Error : oplock break from "
7044 "client for fnum = %d (oplock=%d) and no "
7045 "oplock granted on this file (%s).\n",
7046 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
7048 /* if this is a pure oplock break request then don't
7050 if (num_locks == 0 && num_ulocks == 0) {
7051 END_PROFILE(SMBlockingX);
7054 END_PROFILE(SMBlockingX);
7055 reply_doserror(req, ERRDOS, ERRlock);
7060 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7062 result = remove_oplock(fsp);
7064 result = downgrade_oplock(fsp);
7068 DEBUG(0, ("reply_lockingX: error in removing "
7069 "oplock on file %s\n", fsp->fsp_name));
7070 /* Hmmm. Is this panic justified? */
7071 smb_panic("internal tdb error");
7074 reply_to_oplock_break_requests(fsp);
7076 /* if this is a pure oplock break request then don't send a
7078 if (num_locks == 0 && num_ulocks == 0) {
7079 /* Sanity check - ensure a pure oplock break is not a
7081 if(CVAL(req->vwv+0, 0) != 0xff)
7082 DEBUG(0,("reply_lockingX: Error : pure oplock "
7083 "break is a chained %d request !\n",
7084 (unsigned int)CVAL(req->vwv+0, 0)));
7085 END_PROFILE(SMBlockingX);
7091 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7092 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7093 END_PROFILE(SMBlockingX);
7097 /* Data now points at the beginning of the list
7098 of smb_unlkrng structs */
7099 for(i = 0; i < (int)num_ulocks; i++) {
7100 lock_pid = get_lock_pid( data, i, large_file_format);
7101 count = get_lock_count( data, i, large_file_format);
7102 offset = get_lock_offset( data, i, large_file_format, &err);
7105 * There is no error code marked "stupid client bug".... :-).
7108 END_PROFILE(SMBlockingX);
7109 reply_doserror(req, ERRDOS, ERRnoaccess);
7113 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
7114 "pid %u, file %s\n", (double)offset, (double)count,
7115 (unsigned int)lock_pid, fsp->fsp_name ));
7117 status = do_unlock(smbd_messaging_context(),
7124 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
7125 nt_errstr(status)));
7127 if (NT_STATUS_V(status)) {
7128 END_PROFILE(SMBlockingX);
7129 reply_nterror(req, status);
7134 /* Setup the timeout in seconds. */
7136 if (!lp_blocking_locks(SNUM(conn))) {
7140 /* Now do any requested locks */
7141 data += ((large_file_format ? 20 : 10)*num_ulocks);
7143 /* Data now points at the beginning of the list
7144 of smb_lkrng structs */
7146 for(i = 0; i < (int)num_locks; i++) {
7147 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
7148 READ_LOCK:WRITE_LOCK);
7149 lock_pid = get_lock_pid( data, i, large_file_format);
7150 count = get_lock_count( data, i, large_file_format);
7151 offset = get_lock_offset( data, i, large_file_format, &err);
7154 * There is no error code marked "stupid client bug".... :-).
7157 END_PROFILE(SMBlockingX);
7158 reply_doserror(req, ERRDOS, ERRnoaccess);
7162 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
7163 "%u, file %s timeout = %d\n", (double)offset,
7164 (double)count, (unsigned int)lock_pid,
7165 fsp->fsp_name, (int)lock_timeout ));
7167 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7168 struct blocking_lock_record *blr = NULL;
7170 if (lp_blocking_locks(SNUM(conn))) {
7172 /* Schedule a message to ourselves to
7173 remove the blocking lock record and
7174 return the right error. */
7176 blr = blocking_lock_cancel(fsp,
7182 NT_STATUS_FILE_LOCK_CONFLICT);
7184 END_PROFILE(SMBlockingX);
7189 ERRcancelviolation));
7193 /* Remove a matching pending lock. */
7194 status = do_lock_cancel(fsp,
7201 bool blocking_lock = lock_timeout ? True : False;
7202 bool defer_lock = False;
7203 struct byte_range_lock *br_lck;
7204 uint32 block_smbpid;
7206 br_lck = do_lock(smbd_messaging_context(),
7218 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7219 /* Windows internal resolution for blocking locks seems
7220 to be about 200ms... Don't wait for less than that. JRA. */
7221 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7222 lock_timeout = lp_lock_spin_time();
7227 /* This heuristic seems to match W2K3 very well. If a
7228 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7229 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7230 far as I can tell. Replacement for do_lock_spin(). JRA. */
7232 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7233 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7235 lock_timeout = lp_lock_spin_time();
7238 if (br_lck && defer_lock) {
7240 * A blocking lock was requested. Package up
7241 * this smb into a queued request and push it
7242 * onto the blocking lock queue.
7244 if(push_blocking_lock_request(br_lck,
7255 TALLOC_FREE(br_lck);
7256 END_PROFILE(SMBlockingX);
7261 TALLOC_FREE(br_lck);
7264 if (NT_STATUS_V(status)) {
7265 END_PROFILE(SMBlockingX);
7266 reply_nterror(req, status);
7271 /* If any of the above locks failed, then we must unlock
7272 all of the previous locks (X/Open spec). */
7274 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7278 * Ensure we don't do a remove on the lock that just failed,
7279 * as under POSIX rules, if we have a lock already there, we
7280 * will delete it (and we shouldn't) .....
7282 for(i--; i >= 0; i--) {
7283 lock_pid = get_lock_pid( data, i, large_file_format);
7284 count = get_lock_count( data, i, large_file_format);
7285 offset = get_lock_offset( data, i, large_file_format,
7289 * There is no error code marked "stupid client
7293 END_PROFILE(SMBlockingX);
7294 reply_doserror(req, ERRDOS, ERRnoaccess);
7298 do_unlock(smbd_messaging_context(),
7305 END_PROFILE(SMBlockingX);
7306 reply_nterror(req, status);
7310 reply_outbuf(req, 2, 0);
7312 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7313 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7315 END_PROFILE(SMBlockingX);
7320 #define DBGC_CLASS DBGC_ALL
7322 /****************************************************************************
7323 Reply to a SMBreadbmpx (read block multiplex) request.
7324 Always reply with an error, if someone has a platform really needs this,
7325 please contact vl@samba.org
7326 ****************************************************************************/
7328 void reply_readbmpx(struct smb_request *req)
7330 START_PROFILE(SMBreadBmpx);
7331 reply_doserror(req, ERRSRV, ERRuseSTD);
7332 END_PROFILE(SMBreadBmpx);
7336 /****************************************************************************
7337 Reply to a SMBreadbs (read block multiplex secondary) request.
7338 Always reply with an error, if someone has a platform really needs this,
7339 please contact vl@samba.org
7340 ****************************************************************************/
7342 void reply_readbs(struct smb_request *req)
7344 START_PROFILE(SMBreadBs);
7345 reply_doserror(req, ERRSRV, ERRuseSTD);
7346 END_PROFILE(SMBreadBs);
7350 /****************************************************************************
7351 Reply to a SMBsetattrE.
7352 ****************************************************************************/
7354 void reply_setattrE(struct smb_request *req)
7356 connection_struct *conn = req->conn;
7357 struct smb_file_time ft;
7359 SMB_STRUCT_STAT sbuf;
7362 START_PROFILE(SMBsetattrE);
7366 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7367 END_PROFILE(SMBsetattrE);
7371 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7373 if(!fsp || (fsp->conn != conn)) {
7374 reply_doserror(req, ERRDOS, ERRbadfid);
7375 END_PROFILE(SMBsetattrE);
7381 * Convert the DOS times into unix times.
7384 ft.atime = convert_time_t_to_timespec(
7385 srv_make_unix_date2(req->vwv+3));
7386 ft.mtime = convert_time_t_to_timespec(
7387 srv_make_unix_date2(req->vwv+5));
7388 ft.create_time = convert_time_t_to_timespec(
7389 srv_make_unix_date2(req->vwv+1));
7391 reply_outbuf(req, 0, 0);
7394 * Patch from Ray Frush <frush@engr.colostate.edu>
7395 * Sometimes times are sent as zero - ignore them.
7398 /* Ensure we have a valid stat struct for the source. */
7399 if (fsp->fh->fd != -1) {
7400 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7401 status = map_nt_error_from_unix(errno);
7402 reply_nterror(req, status);
7403 END_PROFILE(SMBsetattrE);
7409 if (fsp->posix_open) {
7410 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
7412 ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
7415 status = map_nt_error_from_unix(errno);
7416 reply_nterror(req, status);
7417 END_PROFILE(SMBsetattrE);
7422 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7424 if (!NT_STATUS_IS_OK(status)) {
7425 reply_doserror(req, ERRDOS, ERRnoaccess);
7426 END_PROFILE(SMBsetattrE);
7430 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7433 (unsigned int)ft.atime.tv_sec,
7434 (unsigned int)ft.mtime.tv_sec,
7435 (unsigned int)ft.create_time.tv_sec
7438 END_PROFILE(SMBsetattrE);
7443 /* Back from the dead for OS/2..... JRA. */
7445 /****************************************************************************
7446 Reply to a SMBwritebmpx (write block multiplex primary) request.
7447 Always reply with an error, if someone has a platform really needs this,
7448 please contact vl@samba.org
7449 ****************************************************************************/
7451 void reply_writebmpx(struct smb_request *req)
7453 START_PROFILE(SMBwriteBmpx);
7454 reply_doserror(req, ERRSRV, ERRuseSTD);
7455 END_PROFILE(SMBwriteBmpx);
7459 /****************************************************************************
7460 Reply to a SMBwritebs (write block multiplex secondary) request.
7461 Always reply with an error, if someone has a platform really needs this,
7462 please contact vl@samba.org
7463 ****************************************************************************/
7465 void reply_writebs(struct smb_request *req)
7467 START_PROFILE(SMBwriteBs);
7468 reply_doserror(req, ERRSRV, ERRuseSTD);
7469 END_PROFILE(SMBwriteBs);
7473 /****************************************************************************
7474 Reply to a SMBgetattrE.
7475 ****************************************************************************/
7477 void reply_getattrE(struct smb_request *req)
7479 connection_struct *conn = req->conn;
7480 SMB_STRUCT_STAT sbuf;
7483 struct timespec create_ts;
7485 START_PROFILE(SMBgetattrE);
7488 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7489 END_PROFILE(SMBgetattrE);
7493 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7495 if(!fsp || (fsp->conn != conn)) {
7496 reply_doserror(req, ERRDOS, ERRbadfid);
7497 END_PROFILE(SMBgetattrE);
7501 /* Do an fstat on this file */
7502 if(fsp_stat(fsp, &sbuf)) {
7503 reply_unixerror(req, ERRDOS, ERRnoaccess);
7504 END_PROFILE(SMBgetattrE);
7508 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7511 * Convert the times into dos times. Set create
7512 * date to be last modify date as UNIX doesn't save
7516 reply_outbuf(req, 11, 0);
7518 create_ts = get_create_timespec(&sbuf,
7519 lp_fake_dir_create_times(SNUM(conn)));
7520 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7521 srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7522 /* Should we check pending modtime here ? JRA */
7523 srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7526 SIVAL(req->outbuf, smb_vwv6, 0);
7527 SIVAL(req->outbuf, smb_vwv8, 0);
7529 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7530 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7531 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7533 SSVAL(req->outbuf,smb_vwv10, mode);
7535 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7537 END_PROFILE(SMBgetattrE);