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;
969 struct smb_filename *smb_fname = NULL;
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, &smb_fname, 0);
1003 if (!NT_STATUS_IS_OK(status)) {
1007 status = get_full_smb_filename(ctx, smb_fname, &name);
1008 if (!NT_STATUS_IS_OK(status)) {
1012 status = check_name(conn, name);
1013 if (!NT_STATUS_IS_OK(status)) {
1014 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
1018 if (!VALID_STAT(smb_fname->st) &&
1019 (SMB_VFS_STAT(conn, name, &smb_fname->st) != 0)) {
1020 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
1021 status = map_nt_error_from_unix(errno);
1025 if (!S_ISDIR(smb_fname->st.st_mode)) {
1026 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1027 ERRDOS, ERRbadpath);
1031 reply_outbuf(req, 0, 0);
1034 TALLOC_FREE(smb_fname);
1036 END_PROFILE(SMBcheckpath);
1042 TALLOC_FREE(smb_fname);
1045 END_PROFILE(SMBcheckpath);
1047 /* We special case this - as when a Windows machine
1048 is parsing a path is steps through the components
1049 one at a time - if a component fails it expects
1050 ERRbadpath, not ERRbadfile.
1052 status = map_checkpath_error(req->flags2, status);
1053 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1055 * Windows returns different error codes if
1056 * the parent directory is valid but not the
1057 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1058 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1059 * if the path is invalid.
1061 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1062 ERRDOS, ERRbadpath);
1066 reply_nterror(req, status);
1069 /****************************************************************************
1071 ****************************************************************************/
1073 void reply_getatr(struct smb_request *req)
1075 connection_struct *conn = req->conn;
1076 struct smb_filename *smb_fname = NULL;
1083 TALLOC_CTX *ctx = talloc_tos();
1085 START_PROFILE(SMBgetatr);
1087 p = (const char *)req->buf + 1;
1088 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1089 if (!NT_STATUS_IS_OK(status)) {
1090 reply_nterror(req, status);
1094 status = resolve_dfspath(ctx, conn,
1095 req->flags2 & FLAGS2_DFS_PATHNAMES,
1098 if (!NT_STATUS_IS_OK(status)) {
1099 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1100 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1101 ERRSRV, ERRbadpath);
1104 reply_nterror(req, status);
1108 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1109 under WfWg - weird! */
1110 if (*fname == '\0') {
1111 mode = aHIDDEN | aDIR;
1112 if (!CAN_WRITE(conn)) {
1118 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1119 if (!NT_STATUS_IS_OK(status)) {
1120 reply_nterror(req, status);
1123 status = get_full_smb_filename(ctx, smb_fname, &fname);
1124 if (!NT_STATUS_IS_OK(status)) {
1125 reply_nterror(req, status);
1128 status = check_name(conn, fname);
1129 if (!NT_STATUS_IS_OK(status)) {
1130 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1131 reply_nterror(req, status);
1134 if (!VALID_STAT(smb_fname->st) &&
1135 (SMB_VFS_STAT(conn, fname, &smb_fname->st) != 0)) {
1136 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1137 reply_unixerror(req, ERRDOS,ERRbadfile);
1141 mode = dos_mode(conn, fname, &smb_fname->st);
1142 size = smb_fname->st.st_size;
1143 mtime = smb_fname->st.st_mtime;
1149 reply_outbuf(req, 10, 0);
1151 SSVAL(req->outbuf,smb_vwv0,mode);
1152 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1153 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1155 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1157 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1159 if (Protocol >= PROTOCOL_NT1) {
1160 SSVAL(req->outbuf, smb_flg2,
1161 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1164 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1168 TALLOC_FREE(smb_fname);
1170 END_PROFILE(SMBgetatr);
1174 /****************************************************************************
1176 ****************************************************************************/
1178 void reply_setatr(struct smb_request *req)
1180 struct smb_file_time ft;
1181 connection_struct *conn = req->conn;
1182 struct smb_filename *smb_fname = NULL;
1188 TALLOC_CTX *ctx = talloc_tos();
1190 START_PROFILE(SMBsetatr);
1195 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1199 p = (const char *)req->buf + 1;
1200 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1201 if (!NT_STATUS_IS_OK(status)) {
1202 reply_nterror(req, status);
1206 status = resolve_dfspath(ctx, conn,
1207 req->flags2 & FLAGS2_DFS_PATHNAMES,
1210 if (!NT_STATUS_IS_OK(status)) {
1211 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1212 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1213 ERRSRV, ERRbadpath);
1216 reply_nterror(req, status);
1220 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1221 if (!NT_STATUS_IS_OK(status)) {
1222 reply_nterror(req, status);
1226 status = get_full_smb_filename(ctx, smb_fname, &fname);
1227 if (!NT_STATUS_IS_OK(status)) {
1228 reply_nterror(req, status);
1232 status = check_name(conn, fname);
1233 if (!NT_STATUS_IS_OK(status)) {
1234 reply_nterror(req, status);
1238 if (fname[0] == '.' && fname[1] == '\0') {
1240 * Not sure here is the right place to catch this
1241 * condition. Might be moved to somewhere else later -- vl
1243 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1247 mode = SVAL(req->vwv+0, 0);
1248 mtime = srv_make_unix_date3(req->vwv+1);
1250 ft.mtime = convert_time_t_to_timespec(mtime);
1251 status = smb_set_file_time(conn, NULL, fname,
1252 &smb_fname->st, &ft, true);
1253 if (!NT_STATUS_IS_OK(status)) {
1254 reply_unixerror(req, ERRDOS, ERRnoaccess);
1258 if (mode != FILE_ATTRIBUTE_NORMAL) {
1259 if (VALID_STAT_OF_DIR(smb_fname->st))
1264 if (file_set_dosmode(conn, fname, mode, &smb_fname->st, NULL,
1266 reply_unixerror(req, ERRDOS, ERRnoaccess);
1271 reply_outbuf(req, 0, 0);
1273 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1276 TALLOC_FREE(smb_fname);
1278 END_PROFILE(SMBsetatr);
1282 /****************************************************************************
1284 ****************************************************************************/
1286 void reply_dskattr(struct smb_request *req)
1288 connection_struct *conn = req->conn;
1289 uint64_t dfree,dsize,bsize;
1290 START_PROFILE(SMBdskattr);
1292 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1293 reply_unixerror(req, ERRHRD, ERRgeneral);
1294 END_PROFILE(SMBdskattr);
1298 reply_outbuf(req, 5, 0);
1300 if (Protocol <= PROTOCOL_LANMAN2) {
1301 double total_space, free_space;
1302 /* we need to scale this to a number that DOS6 can handle. We
1303 use floating point so we can handle large drives on systems
1304 that don't have 64 bit integers
1306 we end up displaying a maximum of 2G to DOS systems
1308 total_space = dsize * (double)bsize;
1309 free_space = dfree * (double)bsize;
1311 dsize = (uint64_t)((total_space+63*512) / (64*512));
1312 dfree = (uint64_t)((free_space+63*512) / (64*512));
1314 if (dsize > 0xFFFF) dsize = 0xFFFF;
1315 if (dfree > 0xFFFF) dfree = 0xFFFF;
1317 SSVAL(req->outbuf,smb_vwv0,dsize);
1318 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1319 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1320 SSVAL(req->outbuf,smb_vwv3,dfree);
1322 SSVAL(req->outbuf,smb_vwv0,dsize);
1323 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1324 SSVAL(req->outbuf,smb_vwv2,512);
1325 SSVAL(req->outbuf,smb_vwv3,dfree);
1328 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1330 END_PROFILE(SMBdskattr);
1334 /****************************************************************************
1336 Can be called from SMBsearch, SMBffirst or SMBfunique.
1337 ****************************************************************************/
1339 void reply_search(struct smb_request *req)
1341 connection_struct *conn = req->conn;
1342 const char *mask = NULL;
1343 char *directory = NULL;
1349 unsigned int numentries = 0;
1350 unsigned int maxentries = 0;
1351 bool finished = False;
1357 bool check_descend = False;
1358 bool expect_close = False;
1360 bool mask_contains_wcard = False;
1361 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1362 TALLOC_CTX *ctx = talloc_tos();
1363 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1365 START_PROFILE(SMBsearch);
1368 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1369 END_PROFILE(SMBsearch);
1373 if (lp_posix_pathnames()) {
1374 reply_unknown_new(req, req->cmd);
1375 END_PROFILE(SMBsearch);
1379 /* If we were called as SMBffirst then we must expect close. */
1380 if(req->cmd == SMBffirst) {
1381 expect_close = True;
1384 reply_outbuf(req, 1, 3);
1385 maxentries = SVAL(req->vwv+0, 0);
1386 dirtype = SVAL(req->vwv+1, 0);
1387 p = (const char *)req->buf + 1;
1388 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1389 &nt_status, &mask_contains_wcard);
1390 if (!NT_STATUS_IS_OK(nt_status)) {
1391 reply_nterror(req, nt_status);
1392 END_PROFILE(SMBsearch);
1396 nt_status = resolve_dfspath_wcard(ctx, conn,
1397 req->flags2 & FLAGS2_DFS_PATHNAMES,
1400 &mask_contains_wcard);
1401 if (!NT_STATUS_IS_OK(nt_status)) {
1402 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1403 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1404 ERRSRV, ERRbadpath);
1405 END_PROFILE(SMBsearch);
1408 reply_nterror(req, nt_status);
1409 END_PROFILE(SMBsearch);
1414 status_len = SVAL(p, 0);
1417 /* dirtype &= ~aDIR; */
1419 if (status_len == 0) {
1420 struct smb_filename *smb_fname = NULL;
1422 nt_status = unix_convert(ctx, conn, path, &smb_fname,
1423 UCF_ALLOW_WCARD_LCOMP);
1424 if (!NT_STATUS_IS_OK(nt_status)) {
1425 reply_nterror(req, nt_status);
1426 END_PROFILE(SMBsearch);
1430 nt_status = get_full_smb_filename(ctx, smb_fname, &directory);
1431 TALLOC_FREE(smb_fname);
1432 if (!NT_STATUS_IS_OK(nt_status)) {
1433 reply_nterror(req, nt_status);
1434 END_PROFILE(SMBsearch);
1438 nt_status = check_name(conn, directory);
1439 if (!NT_STATUS_IS_OK(nt_status)) {
1440 reply_nterror(req, nt_status);
1441 END_PROFILE(SMBsearch);
1445 p = strrchr_m(directory,'/');
1446 if ((p != NULL) && (*directory != '/')) {
1448 directory = talloc_strndup(ctx, directory,
1449 PTR_DIFF(p, directory));
1452 directory = talloc_strdup(ctx,".");
1456 reply_nterror(req, NT_STATUS_NO_MEMORY);
1457 END_PROFILE(SMBsearch);
1461 memset((char *)status,'\0',21);
1462 SCVAL(status,0,(dirtype & 0x1F));
1464 nt_status = dptr_create(conn,
1470 mask_contains_wcard,
1473 if (!NT_STATUS_IS_OK(nt_status)) {
1474 reply_nterror(req, nt_status);
1475 END_PROFILE(SMBsearch);
1478 dptr_num = dptr_dnum(conn->dirptr);
1482 memcpy(status,p,21);
1483 status_dirtype = CVAL(status,0) & 0x1F;
1484 if (status_dirtype != (dirtype & 0x1F)) {
1485 dirtype = status_dirtype;
1488 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1489 if (!conn->dirptr) {
1492 string_set(&conn->dirpath,dptr_path(dptr_num));
1493 mask = dptr_wcard(dptr_num);
1498 * For a 'continue' search we have no string. So
1499 * check from the initial saved string.
1501 mask_contains_wcard = ms_has_wild(mask);
1502 dirtype = dptr_attr(dptr_num);
1505 DEBUG(4,("dptr_num is %d\n",dptr_num));
1507 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1508 dptr_init_search_op(conn->dirptr);
1510 if ((dirtype&0x1F) == aVOLID) {
1511 char buf[DIR_STRUCT_SIZE];
1512 memcpy(buf,status,21);
1513 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1514 0,aVOLID,0,!allow_long_path_components)) {
1515 reply_nterror(req, NT_STATUS_NO_MEMORY);
1516 END_PROFILE(SMBsearch);
1519 dptr_fill(buf+12,dptr_num);
1520 if (dptr_zero(buf+12) && (status_len==0)) {
1525 if (message_push_blob(&req->outbuf,
1526 data_blob_const(buf, sizeof(buf)))
1528 reply_nterror(req, NT_STATUS_NO_MEMORY);
1529 END_PROFILE(SMBsearch);
1537 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1540 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1541 conn->dirpath,lp_dontdescend(SNUM(conn))));
1542 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1543 check_descend = True;
1546 for (i=numentries;(i<maxentries) && !finished;i++) {
1547 finished = !get_dir_entry(ctx,
1558 char buf[DIR_STRUCT_SIZE];
1559 memcpy(buf,status,21);
1560 if (!make_dir_struct(ctx,
1567 !allow_long_path_components)) {
1568 reply_nterror(req, NT_STATUS_NO_MEMORY);
1569 END_PROFILE(SMBsearch);
1572 if (!dptr_fill(buf+12,dptr_num)) {
1575 if (message_push_blob(&req->outbuf,
1576 data_blob_const(buf, sizeof(buf)))
1578 reply_nterror(req, NT_STATUS_NO_MEMORY);
1579 END_PROFILE(SMBsearch);
1589 /* If we were called as SMBffirst with smb_search_id == NULL
1590 and no entries were found then return error and close dirptr
1593 if (numentries == 0) {
1594 dptr_close(&dptr_num);
1595 } else if(expect_close && status_len == 0) {
1596 /* Close the dptr - we know it's gone */
1597 dptr_close(&dptr_num);
1600 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1601 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1602 dptr_close(&dptr_num);
1605 if ((numentries == 0) && !mask_contains_wcard) {
1606 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1607 END_PROFILE(SMBsearch);
1611 SSVAL(req->outbuf,smb_vwv0,numentries);
1612 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1613 SCVAL(smb_buf(req->outbuf),0,5);
1614 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1616 /* The replies here are never long name. */
1617 SSVAL(req->outbuf, smb_flg2,
1618 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1619 if (!allow_long_path_components) {
1620 SSVAL(req->outbuf, smb_flg2,
1621 SVAL(req->outbuf, smb_flg2)
1622 & (~FLAGS2_LONG_PATH_COMPONENTS));
1625 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1626 SSVAL(req->outbuf, smb_flg2,
1627 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1630 directory = dptr_path(dptr_num);
1633 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1634 smb_fn_name(req->cmd),
1636 directory ? directory : "./",
1641 END_PROFILE(SMBsearch);
1645 /****************************************************************************
1646 Reply to a fclose (stop directory search).
1647 ****************************************************************************/
1649 void reply_fclose(struct smb_request *req)
1657 bool path_contains_wcard = False;
1658 TALLOC_CTX *ctx = talloc_tos();
1660 START_PROFILE(SMBfclose);
1662 if (lp_posix_pathnames()) {
1663 reply_unknown_new(req, req->cmd);
1664 END_PROFILE(SMBfclose);
1668 p = (const char *)req->buf + 1;
1669 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1670 &err, &path_contains_wcard);
1671 if (!NT_STATUS_IS_OK(err)) {
1672 reply_nterror(req, err);
1673 END_PROFILE(SMBfclose);
1677 status_len = SVAL(p,0);
1680 if (status_len == 0) {
1681 reply_doserror(req, ERRSRV, ERRsrverror);
1682 END_PROFILE(SMBfclose);
1686 memcpy(status,p,21);
1688 if(dptr_fetch(status+12,&dptr_num)) {
1689 /* Close the dptr - we know it's gone */
1690 dptr_close(&dptr_num);
1693 reply_outbuf(req, 1, 0);
1694 SSVAL(req->outbuf,smb_vwv0,0);
1696 DEBUG(3,("search close\n"));
1698 END_PROFILE(SMBfclose);
1702 /****************************************************************************
1704 ****************************************************************************/
1706 void reply_open(struct smb_request *req)
1708 connection_struct *conn = req->conn;
1714 SMB_STRUCT_STAT sbuf;
1721 uint32 create_disposition;
1722 uint32 create_options = 0;
1724 TALLOC_CTX *ctx = talloc_tos();
1726 START_PROFILE(SMBopen);
1728 SET_STAT_INVALID(sbuf);
1731 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1732 END_PROFILE(SMBopen);
1736 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1737 deny_mode = SVAL(req->vwv+0, 0);
1738 dos_attr = SVAL(req->vwv+1, 0);
1740 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1741 STR_TERMINATE, &status);
1742 if (!NT_STATUS_IS_OK(status)) {
1743 reply_nterror(req, status);
1744 END_PROFILE(SMBopen);
1748 if (!map_open_params_to_ntcreate(
1749 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1750 &share_mode, &create_disposition, &create_options)) {
1751 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1752 END_PROFILE(SMBopen);
1756 status = SMB_VFS_CREATE_FILE(
1759 0, /* root_dir_fid */
1761 CFF_DOS_PATH, /* create_file_flags */
1762 access_mask, /* access_mask */
1763 share_mode, /* share_access */
1764 create_disposition, /* create_disposition*/
1765 create_options, /* create_options */
1766 dos_attr, /* file_attributes */
1767 oplock_request, /* oplock_request */
1768 0, /* allocation_size */
1775 if (!NT_STATUS_IS_OK(status)) {
1776 if (open_was_deferred(req->mid)) {
1777 /* We have re-scheduled this call. */
1778 END_PROFILE(SMBopen);
1781 reply_openerror(req, status);
1782 END_PROFILE(SMBopen);
1786 size = sbuf.st_size;
1787 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1788 mtime = sbuf.st_mtime;
1791 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1792 close_file(req, fsp, ERROR_CLOSE);
1793 reply_doserror(req, ERRDOS,ERRnoaccess);
1794 END_PROFILE(SMBopen);
1798 reply_outbuf(req, 7, 0);
1799 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1800 SSVAL(req->outbuf,smb_vwv1,fattr);
1801 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1802 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1804 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1806 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1807 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1809 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1810 SCVAL(req->outbuf,smb_flg,
1811 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1814 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1815 SCVAL(req->outbuf,smb_flg,
1816 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1818 END_PROFILE(SMBopen);
1822 /****************************************************************************
1823 Reply to an open and X.
1824 ****************************************************************************/
1826 void reply_open_and_X(struct smb_request *req)
1828 connection_struct *conn = req->conn;
1833 /* Breakout the oplock request bits so we can set the
1834 reply bits separately. */
1835 int ex_oplock_request;
1836 int core_oplock_request;
1839 int smb_sattr = SVAL(req->vwv+4, 0);
1840 uint32 smb_time = make_unix_date3(req->vwv+6);
1845 SMB_STRUCT_STAT sbuf;
1849 uint64_t allocation_size;
1850 ssize_t retval = -1;
1853 uint32 create_disposition;
1854 uint32 create_options = 0;
1855 TALLOC_CTX *ctx = talloc_tos();
1857 START_PROFILE(SMBopenX);
1859 if (req->wct < 15) {
1860 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1861 END_PROFILE(SMBopenX);
1865 SET_STAT_INVALID(sbuf);
1867 open_flags = SVAL(req->vwv+2, 0);
1868 deny_mode = SVAL(req->vwv+3, 0);
1869 smb_attr = SVAL(req->vwv+5, 0);
1870 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1871 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1872 oplock_request = ex_oplock_request | core_oplock_request;
1873 smb_ofun = SVAL(req->vwv+8, 0);
1874 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1876 /* If it's an IPC, pass off the pipe handler. */
1878 if (lp_nt_pipe_support()) {
1879 reply_open_pipe_and_X(conn, req);
1881 reply_doserror(req, ERRSRV, ERRaccess);
1883 END_PROFILE(SMBopenX);
1887 /* XXXX we need to handle passed times, sattr and flags */
1888 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1889 STR_TERMINATE, &status);
1890 if (!NT_STATUS_IS_OK(status)) {
1891 reply_nterror(req, status);
1892 END_PROFILE(SMBopenX);
1896 if (!map_open_params_to_ntcreate(
1897 fname, deny_mode, smb_ofun, &access_mask,
1898 &share_mode, &create_disposition, &create_options)) {
1899 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1900 END_PROFILE(SMBopenX);
1904 status = SMB_VFS_CREATE_FILE(
1907 0, /* root_dir_fid */
1909 CFF_DOS_PATH, /* create_file_flags */
1910 access_mask, /* access_mask */
1911 share_mode, /* share_access */
1912 create_disposition, /* create_disposition*/
1913 create_options, /* create_options */
1914 smb_attr, /* file_attributes */
1915 oplock_request, /* oplock_request */
1916 0, /* allocation_size */
1920 &smb_action, /* pinfo */
1923 if (!NT_STATUS_IS_OK(status)) {
1924 END_PROFILE(SMBopenX);
1925 if (open_was_deferred(req->mid)) {
1926 /* We have re-scheduled this call. */
1929 reply_openerror(req, status);
1933 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1934 if the file is truncated or created. */
1935 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1936 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1937 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1938 close_file(req, fsp, ERROR_CLOSE);
1939 reply_nterror(req, NT_STATUS_DISK_FULL);
1940 END_PROFILE(SMBopenX);
1943 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1945 close_file(req, fsp, ERROR_CLOSE);
1946 reply_nterror(req, NT_STATUS_DISK_FULL);
1947 END_PROFILE(SMBopenX);
1950 sbuf.st_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
1953 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1954 mtime = sbuf.st_mtime;
1956 close_file(req, fsp, ERROR_CLOSE);
1957 reply_doserror(req, ERRDOS, ERRnoaccess);
1958 END_PROFILE(SMBopenX);
1962 /* If the caller set the extended oplock request bit
1963 and we granted one (by whatever means) - set the
1964 correct bit for extended oplock reply.
1967 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1968 smb_action |= EXTENDED_OPLOCK_GRANTED;
1971 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1972 smb_action |= EXTENDED_OPLOCK_GRANTED;
1975 /* If the caller set the core oplock request bit
1976 and we granted one (by whatever means) - set the
1977 correct bit for core oplock reply.
1980 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1981 reply_outbuf(req, 19, 0);
1983 reply_outbuf(req, 15, 0);
1986 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1987 SCVAL(req->outbuf, smb_flg,
1988 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1991 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1992 SCVAL(req->outbuf, smb_flg,
1993 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1996 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1997 SSVAL(req->outbuf,smb_vwv3,fattr);
1998 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1999 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2001 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2003 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
2004 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2005 SSVAL(req->outbuf,smb_vwv11,smb_action);
2007 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2008 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2011 END_PROFILE(SMBopenX);
2016 /****************************************************************************
2017 Reply to a SMBulogoffX.
2018 ****************************************************************************/
2020 void reply_ulogoffX(struct smb_request *req)
2024 START_PROFILE(SMBulogoffX);
2026 vuser = get_valid_user_struct(req->vuid);
2029 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2033 /* in user level security we are supposed to close any files
2034 open by this user */
2035 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2036 file_close_user(req->vuid);
2039 invalidate_vuid(req->vuid);
2041 reply_outbuf(req, 2, 0);
2043 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2045 END_PROFILE(SMBulogoffX);
2049 /****************************************************************************
2050 Reply to a mknew or a create.
2051 ****************************************************************************/
2053 void reply_mknew(struct smb_request *req)
2055 connection_struct *conn = req->conn;
2058 struct smb_file_time ft;
2060 int oplock_request = 0;
2061 SMB_STRUCT_STAT sbuf;
2063 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2064 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2065 uint32 create_disposition;
2066 uint32 create_options = 0;
2067 TALLOC_CTX *ctx = talloc_tos();
2069 START_PROFILE(SMBcreate);
2071 SET_STAT_INVALID(sbuf);
2074 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2075 END_PROFILE(SMBcreate);
2079 fattr = SVAL(req->vwv+0, 0);
2080 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2083 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2085 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2086 STR_TERMINATE, &status);
2087 if (!NT_STATUS_IS_OK(status)) {
2088 reply_nterror(req, status);
2089 END_PROFILE(SMBcreate);
2093 if (fattr & aVOLID) {
2094 DEBUG(0,("Attempt to create file (%s) with volid set - "
2095 "please report this\n", fname));
2098 if(req->cmd == SMBmknew) {
2099 /* We should fail if file exists. */
2100 create_disposition = FILE_CREATE;
2102 /* Create if file doesn't exist, truncate if it does. */
2103 create_disposition = FILE_OVERWRITE_IF;
2106 status = SMB_VFS_CREATE_FILE(
2109 0, /* root_dir_fid */
2111 CFF_DOS_PATH, /* create_file_flags */
2112 access_mask, /* access_mask */
2113 share_mode, /* share_access */
2114 create_disposition, /* create_disposition*/
2115 create_options, /* create_options */
2116 fattr, /* file_attributes */
2117 oplock_request, /* oplock_request */
2118 0, /* allocation_size */
2125 if (!NT_STATUS_IS_OK(status)) {
2126 END_PROFILE(SMBcreate);
2127 if (open_was_deferred(req->mid)) {
2128 /* We have re-scheduled this call. */
2131 reply_openerror(req, status);
2135 ft.atime = get_atimespec(&sbuf); /* atime. */
2136 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true);
2137 if (!NT_STATUS_IS_OK(status)) {
2138 END_PROFILE(SMBcreate);
2139 reply_openerror(req, status);
2143 reply_outbuf(req, 1, 0);
2144 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2146 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2147 SCVAL(req->outbuf,smb_flg,
2148 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2151 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2152 SCVAL(req->outbuf,smb_flg,
2153 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2156 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2157 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2158 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2160 END_PROFILE(SMBcreate);
2164 /****************************************************************************
2165 Reply to a create temporary file.
2166 ****************************************************************************/
2168 void reply_ctemp(struct smb_request *req)
2170 connection_struct *conn = req->conn;
2171 struct smb_filename *smb_fname = NULL;
2179 TALLOC_CTX *ctx = talloc_tos();
2181 START_PROFILE(SMBctemp);
2184 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2188 fattr = SVAL(req->vwv+0, 0);
2189 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2191 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2192 STR_TERMINATE, &status);
2193 if (!NT_STATUS_IS_OK(status)) {
2194 reply_nterror(req, status);
2198 fname = talloc_asprintf(ctx,
2202 fname = talloc_strdup(ctx, "TMXXXXXX");
2206 reply_nterror(req, NT_STATUS_NO_MEMORY);
2210 status = resolve_dfspath(ctx, conn,
2211 req->flags2 & FLAGS2_DFS_PATHNAMES,
2214 if (!NT_STATUS_IS_OK(status)) {
2215 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2216 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2217 ERRSRV, ERRbadpath);
2220 reply_nterror(req, status);
2224 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
2225 if (!NT_STATUS_IS_OK(status)) {
2226 reply_nterror(req, status);
2230 status = get_full_smb_filename(ctx, smb_fname, &fname);
2231 if (!NT_STATUS_IS_OK(status)) {
2232 reply_nterror(req, status);
2236 status = check_name(conn, fname);
2237 if (!NT_STATUS_IS_OK(status)) {
2238 reply_nterror(req, status);
2242 tmpfd = mkstemp(fname);
2244 reply_unixerror(req, ERRDOS, ERRnoaccess);
2248 SET_STAT_INVALID(smb_fname->st);
2249 SMB_VFS_STAT(conn, fname, &smb_fname->st);
2251 /* We should fail if file does not exist. */
2252 status = SMB_VFS_CREATE_FILE(
2255 0, /* root_dir_fid */
2257 0, /* create_file_flags */
2258 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2259 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2260 FILE_OPEN, /* create_disposition*/
2261 0, /* create_options */
2262 fattr, /* file_attributes */
2263 oplock_request, /* oplock_request */
2264 0, /* allocation_size */
2269 &smb_fname->st); /* psbuf */
2271 /* close fd from mkstemp() */
2274 if (!NT_STATUS_IS_OK(status)) {
2275 if (open_was_deferred(req->mid)) {
2276 /* We have re-scheduled this call. */
2279 reply_openerror(req, status);
2283 reply_outbuf(req, 1, 0);
2284 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2286 /* the returned filename is relative to the directory */
2287 s = strrchr_m(fsp->fsp_name, '/');
2295 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2296 thing in the byte section. JRA */
2297 SSVALS(p, 0, -1); /* what is this? not in spec */
2299 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2301 reply_nterror(req, NT_STATUS_NO_MEMORY);
2305 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2306 SCVAL(req->outbuf, smb_flg,
2307 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2310 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2311 SCVAL(req->outbuf, smb_flg,
2312 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2315 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2316 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2317 fsp->fh->fd, (unsigned int)smb_fname->st.st_mode));
2320 TALLOC_FREE(smb_fname);
2322 END_PROFILE(SMBctemp);
2326 /*******************************************************************
2327 Check if a user is allowed to rename a file.
2328 ********************************************************************/
2330 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2331 uint16 dirtype, SMB_STRUCT_STAT *pst)
2335 if (!CAN_WRITE(conn)) {
2336 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2339 fmode = dos_mode(conn, fsp->fsp_name, pst);
2340 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2341 return NT_STATUS_NO_SUCH_FILE;
2344 if (S_ISDIR(pst->st_mode)) {
2345 if (fsp->posix_open) {
2346 return NT_STATUS_OK;
2349 /* If no pathnames are open below this
2350 directory, allow the rename. */
2352 if (file_find_subpath(fsp)) {
2353 return NT_STATUS_ACCESS_DENIED;
2355 return NT_STATUS_OK;
2358 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2359 return NT_STATUS_OK;
2362 return NT_STATUS_ACCESS_DENIED;
2365 /*******************************************************************
2366 * unlink a file with all relevant access checks
2367 *******************************************************************/
2369 static NTSTATUS do_unlink(connection_struct *conn,
2370 struct smb_request *req,
2374 SMB_STRUCT_STAT sbuf;
2377 uint32 dirtype_orig = dirtype;
2380 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2382 if (!CAN_WRITE(conn)) {
2383 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2386 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2387 return map_nt_error_from_unix(errno);
2390 fattr = dos_mode(conn,fname,&sbuf);
2392 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2393 dirtype = aDIR|aARCH|aRONLY;
2396 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2398 return NT_STATUS_NO_SUCH_FILE;
2401 if (!dir_check_ftype(conn, fattr, dirtype)) {
2403 return NT_STATUS_FILE_IS_A_DIRECTORY;
2405 return NT_STATUS_NO_SUCH_FILE;
2408 if (dirtype_orig & 0x8000) {
2409 /* These will never be set for POSIX. */
2410 return NT_STATUS_NO_SUCH_FILE;
2414 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2415 return NT_STATUS_FILE_IS_A_DIRECTORY;
2418 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2419 return NT_STATUS_NO_SUCH_FILE;
2422 if (dirtype & 0xFF00) {
2423 /* These will never be set for POSIX. */
2424 return NT_STATUS_NO_SUCH_FILE;
2429 return NT_STATUS_NO_SUCH_FILE;
2432 /* Can't delete a directory. */
2434 return NT_STATUS_FILE_IS_A_DIRECTORY;
2439 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2440 return NT_STATUS_OBJECT_NAME_INVALID;
2441 #endif /* JRATEST */
2443 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2445 On a Windows share, a file with read-only dosmode can be opened with
2446 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2447 fails with NT_STATUS_CANNOT_DELETE error.
2449 This semantic causes a problem that a user can not
2450 rename a file with read-only dosmode on a Samba share
2451 from a Windows command prompt (i.e. cmd.exe, but can rename
2452 from Windows Explorer).
2455 if (!lp_delete_readonly(SNUM(conn))) {
2456 if (fattr & aRONLY) {
2457 return NT_STATUS_CANNOT_DELETE;
2461 /* On open checks the open itself will check the share mode, so
2462 don't do it here as we'll get it wrong. */
2464 status = SMB_VFS_CREATE_FILE
2467 0, /* root_dir_fid */
2469 0, /* create_file_flags */
2470 DELETE_ACCESS, /* access_mask */
2471 FILE_SHARE_NONE, /* share_access */
2472 FILE_OPEN, /* create_disposition*/
2473 FILE_NON_DIRECTORY_FILE, /* create_options */
2474 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2475 0, /* oplock_request */
2476 0, /* allocation_size */
2483 if (!NT_STATUS_IS_OK(status)) {
2484 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2485 nt_errstr(status)));
2489 /* The set is across all open files on this dev/inode pair. */
2490 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2491 close_file(req, fsp, NORMAL_CLOSE);
2492 return NT_STATUS_ACCESS_DENIED;
2495 return close_file(req, fsp, NORMAL_CLOSE);
2498 /****************************************************************************
2499 The guts of the unlink command, split out so it may be called by the NT SMB
2501 ****************************************************************************/
2503 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2504 uint32 dirtype, const char *name_in, bool has_wild)
2506 struct smb_filename *smb_fname = NULL;
2507 const char *directory = NULL;
2512 NTSTATUS status = NT_STATUS_OK;
2514 TALLOC_CTX *ctx = talloc_tos();
2516 status = unix_convert(ctx, conn, name_in, &smb_fname,
2517 has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
2518 if (!NT_STATUS_IS_OK(status)) {
2522 status = get_full_smb_filename(ctx, smb_fname, &name);
2523 if (!NT_STATUS_IS_OK(status)) {
2524 TALLOC_FREE(smb_fname);
2528 p = strrchr_m(name,'/');
2530 directory = talloc_strdup(ctx, ".");
2532 TALLOC_FREE(smb_fname);
2533 return NT_STATUS_NO_MEMORY;
2543 * We should only check the mangled cache
2544 * here if unix_convert failed. This means
2545 * that the path in 'mask' doesn't exist
2546 * on the file system and so we need to look
2547 * for a possible mangle. This patch from
2548 * Tine Smukavec <valentin.smukavec@hermes.si>.
2551 if (!VALID_STAT(smb_fname->st) && mangle_is_mangled(mask,conn->params)) {
2552 char *new_mask = NULL;
2553 mangle_lookup_name_from_8_3(ctx,
2561 TALLOC_FREE(smb_fname);
2564 directory = talloc_asprintf(ctx,
2569 return NT_STATUS_NO_MEMORY;
2572 dirtype = FILE_ATTRIBUTE_NORMAL;
2575 status = check_name(conn, directory);
2576 if (!NT_STATUS_IS_OK(status)) {
2580 status = do_unlink(conn, req, directory, dirtype);
2581 if (!NT_STATUS_IS_OK(status)) {
2587 struct smb_Dir *dir_hnd = NULL;
2591 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2592 return NT_STATUS_OBJECT_NAME_INVALID;
2595 if (strequal(mask,"????????.???")) {
2600 status = check_name(conn, directory);
2601 if (!NT_STATUS_IS_OK(status)) {
2605 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2607 if (dir_hnd == NULL) {
2608 return map_nt_error_from_unix(errno);
2611 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2612 the pattern matches against the long name, otherwise the short name
2613 We don't implement this yet XXXX
2616 status = NT_STATUS_NO_SUCH_FILE;
2618 while ((dname = ReadDirName(dir_hnd, &offset, &st))) {
2621 if (!is_visible_file(conn, directory, dname, &st,
2627 /* Quick check for "." and ".." */
2628 if (ISDOT(dname) || ISDOTDOT(dname)) {
2632 if(!mask_match(dname, mask, conn->case_sensitive)) {
2636 fname = talloc_asprintf(ctx, "%s/%s",
2640 return NT_STATUS_NO_MEMORY;
2643 status = check_name(conn, fname);
2644 if (!NT_STATUS_IS_OK(status)) {
2645 TALLOC_FREE(dir_hnd);
2649 status = do_unlink(conn, req, fname, dirtype);
2650 if (!NT_STATUS_IS_OK(status)) {
2656 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2661 TALLOC_FREE(dir_hnd);
2664 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2665 status = map_nt_error_from_unix(errno);
2671 /****************************************************************************
2673 ****************************************************************************/
2675 void reply_unlink(struct smb_request *req)
2677 connection_struct *conn = req->conn;
2681 bool path_contains_wcard = False;
2682 TALLOC_CTX *ctx = talloc_tos();
2684 START_PROFILE(SMBunlink);
2687 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2688 END_PROFILE(SMBunlink);
2692 dirtype = SVAL(req->vwv+0, 0);
2694 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2695 STR_TERMINATE, &status,
2696 &path_contains_wcard);
2697 if (!NT_STATUS_IS_OK(status)) {
2698 reply_nterror(req, status);
2699 END_PROFILE(SMBunlink);
2703 status = resolve_dfspath_wcard(ctx, conn,
2704 req->flags2 & FLAGS2_DFS_PATHNAMES,
2707 &path_contains_wcard);
2708 if (!NT_STATUS_IS_OK(status)) {
2709 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2710 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2711 ERRSRV, ERRbadpath);
2712 END_PROFILE(SMBunlink);
2715 reply_nterror(req, status);
2716 END_PROFILE(SMBunlink);
2720 DEBUG(3,("reply_unlink : %s\n",name));
2722 status = unlink_internals(conn, req, dirtype, name,
2723 path_contains_wcard);
2724 if (!NT_STATUS_IS_OK(status)) {
2725 if (open_was_deferred(req->mid)) {
2726 /* We have re-scheduled this call. */
2727 END_PROFILE(SMBunlink);
2730 reply_nterror(req, status);
2731 END_PROFILE(SMBunlink);
2735 reply_outbuf(req, 0, 0);
2736 END_PROFILE(SMBunlink);
2741 /****************************************************************************
2743 ****************************************************************************/
2745 static void fail_readraw(void)
2747 const char *errstr = talloc_asprintf(talloc_tos(),
2748 "FAIL ! reply_readbraw: socket write fail (%s)",
2753 exit_server_cleanly(errstr);
2756 /****************************************************************************
2757 Fake (read/write) sendfile. Returns -1 on read or write fail.
2758 ****************************************************************************/
2760 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2764 size_t tosend = nread;
2771 bufsize = MIN(nread, 65536);
2773 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2777 while (tosend > 0) {
2781 if (tosend > bufsize) {
2786 ret = read_file(fsp,buf,startpos,cur_read);
2792 /* If we had a short read, fill with zeros. */
2793 if (ret < cur_read) {
2794 memset(buf + ret, '\0', cur_read - ret);
2797 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2802 startpos += cur_read;
2806 return (ssize_t)nread;
2809 #if defined(WITH_SENDFILE)
2810 /****************************************************************************
2811 Deal with the case of sendfile reading less bytes from the file than
2812 requested. Fill with zeros (all we can do).
2813 ****************************************************************************/
2815 static void sendfile_short_send(files_struct *fsp,
2820 #define SHORT_SEND_BUFSIZE 1024
2821 if (nread < headersize) {
2822 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2823 "header for file %s (%s). Terminating\n",
2824 fsp->fsp_name, strerror(errno) ));
2825 exit_server_cleanly("sendfile_short_send failed");
2828 nread -= headersize;
2830 if (nread < smb_maxcnt) {
2831 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2833 exit_server_cleanly("sendfile_short_send: "
2837 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2838 "with zeros !\n", fsp->fsp_name));
2840 while (nread < smb_maxcnt) {
2842 * We asked for the real file size and told sendfile
2843 * to not go beyond the end of the file. But it can
2844 * happen that in between our fstat call and the
2845 * sendfile call the file was truncated. This is very
2846 * bad because we have already announced the larger
2847 * number of bytes to the client.
2849 * The best we can do now is to send 0-bytes, just as
2850 * a read from a hole in a sparse file would do.
2852 * This should happen rarely enough that I don't care
2853 * about efficiency here :-)
2857 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2858 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2859 exit_server_cleanly("sendfile_short_send: "
2860 "write_data failed");
2867 #endif /* defined WITH_SENDFILE */
2869 /****************************************************************************
2870 Return a readbraw error (4 bytes of zero).
2871 ****************************************************************************/
2873 static void reply_readbraw_error(void)
2877 if (write_data(smbd_server_fd(),header,4) != 4) {
2882 /****************************************************************************
2883 Use sendfile in readbraw.
2884 ****************************************************************************/
2886 static void send_file_readbraw(connection_struct *conn,
2887 struct smb_request *req,
2893 char *outbuf = NULL;
2896 #if defined(WITH_SENDFILE)
2898 * We can only use sendfile on a non-chained packet
2899 * but we can use on a non-oplocked file. tridge proved this
2900 * on a train in Germany :-). JRA.
2901 * reply_readbraw has already checked the length.
2904 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2905 (fsp->wcp == NULL) &&
2906 lp_use_sendfile(SNUM(conn), smbd_server_conn->signing_state) ) {
2907 ssize_t sendfile_read = -1;
2909 DATA_BLOB header_blob;
2911 _smb_setlen(header,nread);
2912 header_blob = data_blob_const(header, 4);
2914 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2915 &header_blob, startpos, nread)) == -1) {
2916 /* Returning ENOSYS means no data at all was sent.
2917 * Do this as a normal read. */
2918 if (errno == ENOSYS) {
2919 goto normal_readbraw;
2923 * Special hack for broken Linux with no working sendfile. If we
2924 * return EINTR we sent the header but not the rest of the data.
2925 * Fake this up by doing read/write calls.
2927 if (errno == EINTR) {
2928 /* Ensure we don't do this again. */
2929 set_use_sendfile(SNUM(conn), False);
2930 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2932 if (fake_sendfile(fsp, startpos, nread) == -1) {
2933 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2934 fsp->fsp_name, strerror(errno) ));
2935 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2940 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2941 fsp->fsp_name, strerror(errno) ));
2942 exit_server_cleanly("send_file_readbraw sendfile failed");
2943 } else if (sendfile_read == 0) {
2945 * Some sendfile implementations return 0 to indicate
2946 * that there was a short read, but nothing was
2947 * actually written to the socket. In this case,
2948 * fallback to the normal read path so the header gets
2949 * the correct byte count.
2951 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2952 "bytes falling back to the normal read: "
2953 "%s\n", fsp->fsp_name));
2954 goto normal_readbraw;
2957 /* Deal with possible short send. */
2958 if (sendfile_read != 4+nread) {
2959 sendfile_short_send(fsp, sendfile_read, 4, nread);
2967 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2969 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2970 (unsigned)(nread+4)));
2971 reply_readbraw_error();
2976 ret = read_file(fsp,outbuf+4,startpos,nread);
2977 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2986 _smb_setlen(outbuf,ret);
2987 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2990 TALLOC_FREE(outbuf);
2993 /****************************************************************************
2994 Reply to a readbraw (core+ protocol).
2995 ****************************************************************************/
2997 void reply_readbraw(struct smb_request *req)
2999 connection_struct *conn = req->conn;
3000 ssize_t maxcount,mincount;
3004 struct lock_struct lock;
3008 START_PROFILE(SMBreadbraw);
3010 if (srv_is_signing_active(smbd_server_conn) ||
3011 is_encrypted_packet(req->inbuf)) {
3012 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3013 "raw reads/writes are disallowed.");
3017 reply_readbraw_error();
3018 END_PROFILE(SMBreadbraw);
3023 * Special check if an oplock break has been issued
3024 * and the readraw request croses on the wire, we must
3025 * return a zero length response here.
3028 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3031 * We have to do a check_fsp by hand here, as
3032 * we must always return 4 zero bytes on error,
3036 if (!fsp || !conn || conn != fsp->conn ||
3037 req->vuid != fsp->vuid ||
3038 fsp->is_directory || fsp->fh->fd == -1) {
3040 * fsp could be NULL here so use the value from the packet. JRA.
3042 DEBUG(3,("reply_readbraw: fnum %d not valid "
3044 (int)SVAL(req->vwv+0, 0)));
3045 reply_readbraw_error();
3046 END_PROFILE(SMBreadbraw);
3050 /* Do a "by hand" version of CHECK_READ. */
3051 if (!(fsp->can_read ||
3052 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3053 (fsp->access_mask & FILE_EXECUTE)))) {
3054 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3055 (int)SVAL(req->vwv+0, 0)));
3056 reply_readbraw_error();
3057 END_PROFILE(SMBreadbraw);
3061 flush_write_cache(fsp, READRAW_FLUSH);
3063 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3064 if(req->wct == 10) {
3066 * This is a large offset (64 bit) read.
3068 #ifdef LARGE_SMB_OFF_T
3070 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3072 #else /* !LARGE_SMB_OFF_T */
3075 * Ensure we haven't been sent a >32 bit offset.
3078 if(IVAL(req->vwv+8, 0) != 0) {
3079 DEBUG(0,("reply_readbraw: large offset "
3080 "(%x << 32) used and we don't support "
3081 "64 bit offsets.\n",
3082 (unsigned int)IVAL(req->vwv+8, 0) ));
3083 reply_readbraw_error();
3084 END_PROFILE(SMBreadbraw);
3088 #endif /* LARGE_SMB_OFF_T */
3091 DEBUG(0,("reply_readbraw: negative 64 bit "
3092 "readraw offset (%.0f) !\n",
3093 (double)startpos ));
3094 reply_readbraw_error();
3095 END_PROFILE(SMBreadbraw);
3100 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3101 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3103 /* ensure we don't overrun the packet size */
3104 maxcount = MIN(65535,maxcount);
3106 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3107 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3110 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3111 reply_readbraw_error();
3112 END_PROFILE(SMBreadbraw);
3116 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3120 if (startpos >= size) {
3123 nread = MIN(maxcount,(size - startpos));
3126 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3127 if (nread < mincount)
3131 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3132 "min=%lu nread=%lu\n",
3133 fsp->fnum, (double)startpos,
3134 (unsigned long)maxcount,
3135 (unsigned long)mincount,
3136 (unsigned long)nread ) );
3138 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3140 DEBUG(5,("reply_readbraw finished\n"));
3142 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3144 END_PROFILE(SMBreadbraw);
3149 #define DBGC_CLASS DBGC_LOCKING
3151 /****************************************************************************
3152 Reply to a lockread (core+ protocol).
3153 ****************************************************************************/
3155 void reply_lockread(struct smb_request *req)
3157 connection_struct *conn = req->conn;
3164 struct byte_range_lock *br_lck = NULL;
3167 START_PROFILE(SMBlockread);
3170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3171 END_PROFILE(SMBlockread);
3175 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3177 if (!check_fsp(conn, req, fsp)) {
3178 END_PROFILE(SMBlockread);
3182 if (!CHECK_READ(fsp,req)) {
3183 reply_doserror(req, ERRDOS, ERRbadaccess);
3184 END_PROFILE(SMBlockread);
3188 numtoread = SVAL(req->vwv+1, 0);
3189 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3191 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3193 reply_outbuf(req, 5, numtoread + 3);
3195 data = smb_buf(req->outbuf) + 3;
3198 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3199 * protocol request that predates the read/write lock concept.
3200 * Thus instead of asking for a read lock here we need to ask
3201 * for a write lock. JRA.
3202 * Note that the requested lock size is unaffected by max_recv.
3205 br_lck = do_lock(smbd_messaging_context(),
3208 (uint64_t)numtoread,
3212 False, /* Non-blocking lock. */
3216 TALLOC_FREE(br_lck);
3218 if (NT_STATUS_V(status)) {
3219 reply_nterror(req, status);
3220 END_PROFILE(SMBlockread);
3225 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3228 if (numtoread > max_recv) {
3229 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3230 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3231 (unsigned int)numtoread, (unsigned int)max_recv ));
3232 numtoread = MIN(numtoread,max_recv);
3234 nread = read_file(fsp,data,startpos,numtoread);
3237 reply_unixerror(req, ERRDOS, ERRnoaccess);
3238 END_PROFILE(SMBlockread);
3242 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3244 SSVAL(req->outbuf,smb_vwv0,nread);
3245 SSVAL(req->outbuf,smb_vwv5,nread+3);
3246 p = smb_buf(req->outbuf);
3247 SCVAL(p,0,0); /* pad byte. */
3250 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3251 fsp->fnum, (int)numtoread, (int)nread));
3253 END_PROFILE(SMBlockread);
3258 #define DBGC_CLASS DBGC_ALL
3260 /****************************************************************************
3262 ****************************************************************************/
3264 void reply_read(struct smb_request *req)
3266 connection_struct *conn = req->conn;
3273 struct lock_struct lock;
3275 START_PROFILE(SMBread);
3278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3279 END_PROFILE(SMBread);
3283 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3285 if (!check_fsp(conn, req, fsp)) {
3286 END_PROFILE(SMBread);
3290 if (!CHECK_READ(fsp,req)) {
3291 reply_doserror(req, ERRDOS, ERRbadaccess);
3292 END_PROFILE(SMBread);
3296 numtoread = SVAL(req->vwv+1, 0);
3297 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3299 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3302 * The requested read size cannot be greater than max_recv. JRA.
3304 if (numtoread > max_recv) {
3305 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3306 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3307 (unsigned int)numtoread, (unsigned int)max_recv ));
3308 numtoread = MIN(numtoread,max_recv);
3311 reply_outbuf(req, 5, numtoread+3);
3313 data = smb_buf(req->outbuf) + 3;
3315 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3316 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3319 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3320 reply_doserror(req, ERRDOS,ERRlock);
3321 END_PROFILE(SMBread);
3326 nread = read_file(fsp,data,startpos,numtoread);
3329 reply_unixerror(req, ERRDOS,ERRnoaccess);
3333 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3335 SSVAL(req->outbuf,smb_vwv0,nread);
3336 SSVAL(req->outbuf,smb_vwv5,nread+3);
3337 SCVAL(smb_buf(req->outbuf),0,1);
3338 SSVAL(smb_buf(req->outbuf),1,nread);
3340 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3341 fsp->fnum, (int)numtoread, (int)nread ) );
3344 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3346 END_PROFILE(SMBread);
3350 /****************************************************************************
3352 ****************************************************************************/
3354 static int setup_readX_header(struct smb_request *req, char *outbuf,
3360 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3361 data = smb_buf(outbuf);
3363 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3365 SCVAL(outbuf,smb_vwv0,0xFF);
3366 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3367 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3368 SSVAL(outbuf,smb_vwv6,
3370 + 1 /* the wct field */
3371 + 12 * sizeof(uint16_t) /* vwv */
3372 + 2); /* the buflen field */
3373 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3374 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3375 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3376 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3380 /****************************************************************************
3381 Reply to a read and X - possibly using sendfile.
3382 ****************************************************************************/
3384 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3385 files_struct *fsp, SMB_OFF_T startpos,
3388 SMB_STRUCT_STAT sbuf;
3390 struct lock_struct lock;
3392 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3393 reply_unixerror(req, ERRDOS, ERRnoaccess);
3397 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3398 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3401 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3402 reply_doserror(req, ERRDOS, ERRlock);
3406 if (!S_ISREG(sbuf.st_mode) || (startpos > sbuf.st_size)
3407 || (smb_maxcnt > (sbuf.st_size - startpos))) {
3409 * We already know that we would do a short read, so don't
3410 * try the sendfile() path.
3412 goto nosendfile_read;
3415 #if defined(WITH_SENDFILE)
3417 * We can only use sendfile on a non-chained packet
3418 * but we can use on a non-oplocked file. tridge proved this
3419 * on a train in Germany :-). JRA.
3422 if (!req_is_in_chain(req) &&
3423 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3424 (fsp->wcp == NULL) &&
3425 lp_use_sendfile(SNUM(conn), smbd_server_conn->signing_state) ) {
3426 uint8 headerbuf[smb_size + 12 * 2];
3430 * Set up the packet header before send. We
3431 * assume here the sendfile will work (get the
3432 * correct amount of data).
3435 header = data_blob_const(headerbuf, sizeof(headerbuf));
3437 construct_reply_common_req(req, (char *)headerbuf);
3438 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3440 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3441 /* Returning ENOSYS means no data at all was sent.
3442 Do this as a normal read. */
3443 if (errno == ENOSYS) {
3448 * Special hack for broken Linux with no working sendfile. If we
3449 * return EINTR we sent the header but not the rest of the data.
3450 * Fake this up by doing read/write calls.
3453 if (errno == EINTR) {
3454 /* Ensure we don't do this again. */
3455 set_use_sendfile(SNUM(conn), False);
3456 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3457 nread = fake_sendfile(fsp, startpos,
3460 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3461 fsp->fsp_name, strerror(errno) ));
3462 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3464 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3465 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3466 /* No outbuf here means successful sendfile. */
3470 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3471 fsp->fsp_name, strerror(errno) ));
3472 exit_server_cleanly("send_file_readX sendfile failed");
3473 } else if (nread == 0) {
3475 * Some sendfile implementations return 0 to indicate
3476 * that there was a short read, but nothing was
3477 * actually written to the socket. In this case,
3478 * fallback to the normal read path so the header gets
3479 * the correct byte count.
3481 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3482 "falling back to the normal read: %s\n",
3487 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3488 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3490 /* Deal with possible short send. */
3491 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3492 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3494 /* No outbuf here means successful sendfile. */
3495 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3496 SMB_PERFCOUNT_END(&req->pcd);
3504 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3505 uint8 headerbuf[smb_size + 2*12];
3507 construct_reply_common_req(req, (char *)headerbuf);
3508 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3510 /* Send out the header. */
3511 if (write_data(smbd_server_fd(), (char *)headerbuf,
3512 sizeof(headerbuf)) != sizeof(headerbuf)) {
3513 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3514 fsp->fsp_name, strerror(errno) ));
3515 exit_server_cleanly("send_file_readX sendfile failed");
3517 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3519 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3520 fsp->fsp_name, strerror(errno) ));
3521 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3528 reply_outbuf(req, 12, smb_maxcnt);
3530 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3532 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3535 reply_unixerror(req, ERRDOS, ERRnoaccess);
3539 setup_readX_header(req, (char *)req->outbuf, nread);
3541 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3542 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3548 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3549 TALLOC_FREE(req->outbuf);
3553 /****************************************************************************
3554 Reply to a read and X.
3555 ****************************************************************************/
3557 void reply_read_and_X(struct smb_request *req)
3559 connection_struct *conn = req->conn;
3563 bool big_readX = False;
3565 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3568 START_PROFILE(SMBreadX);
3570 if ((req->wct != 10) && (req->wct != 12)) {
3571 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3575 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3576 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3577 smb_maxcnt = SVAL(req->vwv+5, 0);
3579 /* If it's an IPC, pass off the pipe handler. */
3581 reply_pipe_read_and_X(req);
3582 END_PROFILE(SMBreadX);
3586 if (!check_fsp(conn, req, fsp)) {
3587 END_PROFILE(SMBreadX);
3591 if (!CHECK_READ(fsp,req)) {
3592 reply_doserror(req, ERRDOS,ERRbadaccess);
3593 END_PROFILE(SMBreadX);
3597 if (global_client_caps & CAP_LARGE_READX) {
3598 size_t upper_size = SVAL(req->vwv+7, 0);
3599 smb_maxcnt |= (upper_size<<16);
3600 if (upper_size > 1) {
3601 /* Can't do this on a chained packet. */
3602 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3603 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3604 END_PROFILE(SMBreadX);
3607 /* We currently don't do this on signed or sealed data. */
3608 if (srv_is_signing_active(smbd_server_conn) ||
3609 is_encrypted_packet(req->inbuf)) {
3610 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3611 END_PROFILE(SMBreadX);
3614 /* Is there room in the reply for this data ? */
3615 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3617 NT_STATUS_INVALID_PARAMETER);
3618 END_PROFILE(SMBreadX);
3625 if (req->wct == 12) {
3626 #ifdef LARGE_SMB_OFF_T
3628 * This is a large offset (64 bit) read.
3630 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3632 #else /* !LARGE_SMB_OFF_T */
3635 * Ensure we haven't been sent a >32 bit offset.
3638 if(IVAL(req->vwv+10, 0) != 0) {
3639 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3640 "used and we don't support 64 bit offsets.\n",
3641 (unsigned int)IVAL(req->vwv+10, 0) ));
3642 END_PROFILE(SMBreadX);
3643 reply_doserror(req, ERRDOS, ERRbadaccess);
3647 #endif /* LARGE_SMB_OFF_T */
3652 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3656 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3659 END_PROFILE(SMBreadX);
3663 /****************************************************************************
3664 Error replies to writebraw must have smb_wct == 1. Fix this up.
3665 ****************************************************************************/
3667 void error_to_writebrawerr(struct smb_request *req)
3669 uint8 *old_outbuf = req->outbuf;
3671 reply_outbuf(req, 1, 0);
3673 memcpy(req->outbuf, old_outbuf, smb_size);
3674 TALLOC_FREE(old_outbuf);
3677 /****************************************************************************
3678 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3679 ****************************************************************************/
3681 void reply_writebraw(struct smb_request *req)
3683 connection_struct *conn = req->conn;
3686 ssize_t total_written=0;
3687 size_t numtowrite=0;
3693 struct lock_struct lock;
3696 START_PROFILE(SMBwritebraw);
3699 * If we ever reply with an error, it must have the SMB command
3700 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3703 SCVAL(req->inbuf,smb_com,SMBwritec);
3705 if (srv_is_signing_active(smbd_server_conn)) {
3706 END_PROFILE(SMBwritebraw);
3707 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3708 "raw reads/writes are disallowed.");
3711 if (req->wct < 12) {
3712 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3713 error_to_writebrawerr(req);
3714 END_PROFILE(SMBwritebraw);
3718 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3719 if (!check_fsp(conn, req, fsp)) {
3720 error_to_writebrawerr(req);
3721 END_PROFILE(SMBwritebraw);
3725 if (!CHECK_WRITE(fsp)) {
3726 reply_doserror(req, ERRDOS, ERRbadaccess);
3727 error_to_writebrawerr(req);
3728 END_PROFILE(SMBwritebraw);
3732 tcount = IVAL(req->vwv+1, 0);
3733 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3734 write_through = BITSETW(req->vwv+7,0);
3736 /* We have to deal with slightly different formats depending
3737 on whether we are using the core+ or lanman1.0 protocol */
3739 if(Protocol <= PROTOCOL_COREPLUS) {
3740 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3741 data = smb_buf(req->inbuf);
3743 numtowrite = SVAL(req->vwv+10, 0);
3744 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3747 /* Ensure we don't write bytes past the end of this packet. */
3748 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3749 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3750 error_to_writebrawerr(req);
3751 END_PROFILE(SMBwritebraw);
3755 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3756 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3759 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3760 reply_doserror(req, ERRDOS, ERRlock);
3761 error_to_writebrawerr(req);
3762 END_PROFILE(SMBwritebraw);
3767 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3770 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3771 "wrote=%d sync=%d\n",
3772 fsp->fnum, (double)startpos, (int)numtowrite,
3773 (int)nwritten, (int)write_through));
3775 if (nwritten < (ssize_t)numtowrite) {
3776 reply_unixerror(req, ERRHRD, ERRdiskfull);
3777 error_to_writebrawerr(req);
3781 total_written = nwritten;
3783 /* Allocate a buffer of 64k + length. */
3784 buf = TALLOC_ARRAY(NULL, char, 65540);
3786 reply_doserror(req, ERRDOS, ERRnomem);
3787 error_to_writebrawerr(req);
3791 /* Return a SMBwritebraw message to the redirector to tell
3792 * it to send more bytes */
3794 memcpy(buf, req->inbuf, smb_size);
3795 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3796 SCVAL(buf,smb_com,SMBwritebraw);
3797 SSVALS(buf,smb_vwv0,0xFFFF);
3799 if (!srv_send_smb(smbd_server_fd(),
3801 false, 0, /* no signing */
3802 IS_CONN_ENCRYPTED(conn),
3804 exit_server_cleanly("reply_writebraw: srv_send_smb "
3808 /* Now read the raw data into the buffer and write it */
3809 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3811 if (!NT_STATUS_IS_OK(status)) {
3812 exit_server_cleanly("secondary writebraw failed");
3815 /* Set up outbuf to return the correct size */
3816 reply_outbuf(req, 1, 0);
3818 if (numtowrite != 0) {
3820 if (numtowrite > 0xFFFF) {
3821 DEBUG(0,("reply_writebraw: Oversize secondary write "
3822 "raw requested (%u). Terminating\n",
3823 (unsigned int)numtowrite ));
3824 exit_server_cleanly("secondary writebraw failed");
3827 if (tcount > nwritten+numtowrite) {
3828 DEBUG(3,("reply_writebraw: Client overestimated the "
3830 (int)tcount,(int)nwritten,(int)numtowrite));
3833 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3835 if (!NT_STATUS_IS_OK(status)) {
3836 DEBUG(0,("reply_writebraw: Oversize secondary write "
3837 "raw read failed (%s). Terminating\n",
3838 nt_errstr(status)));
3839 exit_server_cleanly("secondary writebraw failed");
3842 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3843 if (nwritten == -1) {
3845 reply_unixerror(req, ERRHRD, ERRdiskfull);
3846 error_to_writebrawerr(req);
3850 if (nwritten < (ssize_t)numtowrite) {
3851 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3852 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3856 total_written += nwritten;
3861 SSVAL(req->outbuf,smb_vwv0,total_written);
3863 status = sync_file(conn, fsp, write_through);
3864 if (!NT_STATUS_IS_OK(status)) {
3865 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3866 fsp->fsp_name, nt_errstr(status) ));
3867 reply_nterror(req, status);
3868 error_to_writebrawerr(req);
3872 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3874 fsp->fnum, (double)startpos, (int)numtowrite,
3875 (int)total_written));
3877 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3879 /* We won't return a status if write through is not selected - this
3880 * follows what WfWg does */
3881 END_PROFILE(SMBwritebraw);
3883 if (!write_through && total_written==tcount) {
3885 #if RABBIT_PELLET_FIX
3887 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3888 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3891 if (!send_keepalive(smbd_server_fd())) {
3892 exit_server_cleanly("reply_writebraw: send of "
3893 "keepalive failed");
3896 TALLOC_FREE(req->outbuf);
3901 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3903 END_PROFILE(SMBwritebraw);
3908 #define DBGC_CLASS DBGC_LOCKING
3910 /****************************************************************************
3911 Reply to a writeunlock (core+).
3912 ****************************************************************************/
3914 void reply_writeunlock(struct smb_request *req)
3916 connection_struct *conn = req->conn;
3917 ssize_t nwritten = -1;
3921 NTSTATUS status = NT_STATUS_OK;
3923 struct lock_struct lock;
3925 START_PROFILE(SMBwriteunlock);
3928 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3929 END_PROFILE(SMBwriteunlock);
3933 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3935 if (!check_fsp(conn, req, fsp)) {
3936 END_PROFILE(SMBwriteunlock);
3940 if (!CHECK_WRITE(fsp)) {
3941 reply_doserror(req, ERRDOS,ERRbadaccess);
3942 END_PROFILE(SMBwriteunlock);
3946 numtowrite = SVAL(req->vwv+1, 0);
3947 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3948 data = (const char *)req->buf + 3;
3951 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3952 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3955 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3956 reply_doserror(req, ERRDOS, ERRlock);
3957 END_PROFILE(SMBwriteunlock);
3962 /* The special X/Open SMB protocol handling of
3963 zero length writes is *NOT* done for
3965 if(numtowrite == 0) {
3968 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3971 status = sync_file(conn, fsp, False /* write through */);
3972 if (!NT_STATUS_IS_OK(status)) {
3973 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3974 fsp->fsp_name, nt_errstr(status) ));
3975 reply_nterror(req, status);
3979 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3980 reply_unixerror(req, ERRHRD, ERRdiskfull);
3985 status = do_unlock(smbd_messaging_context(),
3988 (uint64_t)numtowrite,
3992 if (NT_STATUS_V(status)) {
3993 reply_nterror(req, status);
3998 reply_outbuf(req, 1, 0);
4000 SSVAL(req->outbuf,smb_vwv0,nwritten);
4002 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4003 fsp->fnum, (int)numtowrite, (int)nwritten));
4007 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4010 END_PROFILE(SMBwriteunlock);
4015 #define DBGC_CLASS DBGC_ALL
4017 /****************************************************************************
4019 ****************************************************************************/
4021 void reply_write(struct smb_request *req)
4023 connection_struct *conn = req->conn;
4025 ssize_t nwritten = -1;
4029 struct lock_struct lock;
4032 START_PROFILE(SMBwrite);
4035 END_PROFILE(SMBwrite);
4036 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4040 /* If it's an IPC, pass off the pipe handler. */
4042 reply_pipe_write(req);
4043 END_PROFILE(SMBwrite);
4047 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4049 if (!check_fsp(conn, req, fsp)) {
4050 END_PROFILE(SMBwrite);
4054 if (!CHECK_WRITE(fsp)) {
4055 reply_doserror(req, ERRDOS, ERRbadaccess);
4056 END_PROFILE(SMBwrite);
4060 numtowrite = SVAL(req->vwv+1, 0);
4061 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4062 data = (const char *)req->buf + 3;
4064 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4065 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4068 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4069 reply_doserror(req, ERRDOS, ERRlock);
4070 END_PROFILE(SMBwrite);
4075 * X/Open SMB protocol says that if smb_vwv1 is
4076 * zero then the file size should be extended or
4077 * truncated to the size given in smb_vwv[2-3].
4080 if(numtowrite == 0) {
4082 * This is actually an allocate call, and set EOF. JRA.
4084 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4086 reply_nterror(req, NT_STATUS_DISK_FULL);
4089 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4091 reply_nterror(req, NT_STATUS_DISK_FULL);
4094 trigger_write_time_update_immediate(fsp);
4096 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4099 status = sync_file(conn, fsp, False);
4100 if (!NT_STATUS_IS_OK(status)) {
4101 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4102 fsp->fsp_name, nt_errstr(status) ));
4103 reply_nterror(req, status);
4107 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4108 reply_unixerror(req, ERRHRD, ERRdiskfull);
4112 reply_outbuf(req, 1, 0);
4114 SSVAL(req->outbuf,smb_vwv0,nwritten);
4116 if (nwritten < (ssize_t)numtowrite) {
4117 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4118 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4121 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4124 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4126 END_PROFILE(SMBwrite);
4130 /****************************************************************************
4131 Ensure a buffer is a valid writeX for recvfile purposes.
4132 ****************************************************************************/
4134 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4135 (2*14) + /* word count (including bcc) */ \
4138 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4141 connection_struct *conn = NULL;
4142 unsigned int doff = 0;
4143 size_t len = smb_len_large(inbuf);
4145 if (is_encrypted_packet(inbuf)) {
4146 /* Can't do this on encrypted
4151 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4155 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4156 CVAL(inbuf,smb_wct) != 14) {
4157 DEBUG(10,("is_valid_writeX_buffer: chained or "
4158 "invalid word length.\n"));
4162 conn = conn_find(SVAL(inbuf, smb_tid));
4164 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4168 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4171 if (IS_PRINT(conn)) {
4172 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4175 doff = SVAL(inbuf,smb_vwv11);
4177 numtowrite = SVAL(inbuf,smb_vwv10);
4179 if (len > doff && len - doff > 0xFFFF) {
4180 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4183 if (numtowrite == 0) {
4184 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4188 /* Ensure the sizes match up. */
4189 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4190 /* no pad byte...old smbclient :-( */
4191 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4193 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4197 if (len - doff != numtowrite) {
4198 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4199 "len = %u, doff = %u, numtowrite = %u\n",
4202 (unsigned int)numtowrite ));
4206 DEBUG(10,("is_valid_writeX_buffer: true "
4207 "len = %u, doff = %u, numtowrite = %u\n",
4210 (unsigned int)numtowrite ));
4215 /****************************************************************************
4216 Reply to a write and X.
4217 ****************************************************************************/
4219 void reply_write_and_X(struct smb_request *req)
4221 connection_struct *conn = req->conn;
4223 struct lock_struct lock;
4228 unsigned int smb_doff;
4229 unsigned int smblen;
4233 START_PROFILE(SMBwriteX);
4235 if ((req->wct != 12) && (req->wct != 14)) {
4236 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4237 END_PROFILE(SMBwriteX);
4241 numtowrite = SVAL(req->vwv+10, 0);
4242 smb_doff = SVAL(req->vwv+11, 0);
4243 smblen = smb_len(req->inbuf);
4245 if (req->unread_bytes > 0xFFFF ||
4246 (smblen > smb_doff &&
4247 smblen - smb_doff > 0xFFFF)) {
4248 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4251 if (req->unread_bytes) {
4252 /* Can't do a recvfile write on IPC$ */
4254 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4255 END_PROFILE(SMBwriteX);
4258 if (numtowrite != req->unread_bytes) {
4259 reply_doserror(req, ERRDOS, ERRbadmem);
4260 END_PROFILE(SMBwriteX);
4264 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4265 smb_doff + numtowrite > smblen) {
4266 reply_doserror(req, ERRDOS, ERRbadmem);
4267 END_PROFILE(SMBwriteX);
4272 /* If it's an IPC, pass off the pipe handler. */
4274 if (req->unread_bytes) {
4275 reply_doserror(req, ERRDOS, ERRbadmem);
4276 END_PROFILE(SMBwriteX);
4279 reply_pipe_write_and_X(req);
4280 END_PROFILE(SMBwriteX);
4284 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4285 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4286 write_through = BITSETW(req->vwv+7,0);
4288 if (!check_fsp(conn, req, fsp)) {
4289 END_PROFILE(SMBwriteX);
4293 if (!CHECK_WRITE(fsp)) {
4294 reply_doserror(req, ERRDOS, ERRbadaccess);
4295 END_PROFILE(SMBwriteX);
4299 data = smb_base(req->inbuf) + smb_doff;
4301 if(req->wct == 14) {
4302 #ifdef LARGE_SMB_OFF_T
4304 * This is a large offset (64 bit) write.
4306 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4308 #else /* !LARGE_SMB_OFF_T */
4311 * Ensure we haven't been sent a >32 bit offset.
4314 if(IVAL(req->vwv+12, 0) != 0) {
4315 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4316 "used and we don't support 64 bit offsets.\n",
4317 (unsigned int)IVAL(req->vwv+12, 0) ));
4318 reply_doserror(req, ERRDOS, ERRbadaccess);
4319 END_PROFILE(SMBwriteX);
4323 #endif /* LARGE_SMB_OFF_T */
4326 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4327 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4330 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4331 reply_doserror(req, ERRDOS, ERRlock);
4332 END_PROFILE(SMBwriteX);
4336 /* X/Open SMB protocol says that, unlike SMBwrite
4337 if the length is zero then NO truncation is
4338 done, just a write of zero. To truncate a file,
4341 if(numtowrite == 0) {
4345 if ((req->unread_bytes == 0) &&
4346 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4351 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4354 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4355 reply_unixerror(req, ERRHRD, ERRdiskfull);
4359 reply_outbuf(req, 6, 0);
4360 SSVAL(req->outbuf,smb_vwv2,nwritten);
4361 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4363 if (nwritten < (ssize_t)numtowrite) {
4364 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4365 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4368 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4369 fsp->fnum, (int)numtowrite, (int)nwritten));
4371 status = sync_file(conn, fsp, write_through);
4372 if (!NT_STATUS_IS_OK(status)) {
4373 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4374 fsp->fsp_name, nt_errstr(status) ));
4375 reply_nterror(req, status);
4379 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4381 END_PROFILE(SMBwriteX);
4386 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4388 END_PROFILE(SMBwriteX);
4392 /****************************************************************************
4394 ****************************************************************************/
4396 void reply_lseek(struct smb_request *req)
4398 connection_struct *conn = req->conn;
4404 START_PROFILE(SMBlseek);
4407 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4408 END_PROFILE(SMBlseek);
4412 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4414 if (!check_fsp(conn, req, fsp)) {
4418 flush_write_cache(fsp, SEEK_FLUSH);
4420 mode = SVAL(req->vwv+1, 0) & 3;
4421 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4422 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4431 res = fsp->fh->pos + startpos;
4442 if (umode == SEEK_END) {
4443 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4444 if(errno == EINVAL) {
4445 SMB_OFF_T current_pos = startpos;
4446 SMB_STRUCT_STAT sbuf;
4448 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4449 reply_unixerror(req, ERRDOS,
4451 END_PROFILE(SMBlseek);
4455 current_pos += sbuf.st_size;
4457 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4462 reply_unixerror(req, ERRDOS, ERRnoaccess);
4463 END_PROFILE(SMBlseek);
4470 reply_outbuf(req, 2, 0);
4471 SIVAL(req->outbuf,smb_vwv0,res);
4473 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4474 fsp->fnum, (double)startpos, (double)res, mode));
4476 END_PROFILE(SMBlseek);
4480 /****************************************************************************
4482 ****************************************************************************/
4484 void reply_flush(struct smb_request *req)
4486 connection_struct *conn = req->conn;
4490 START_PROFILE(SMBflush);
4493 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4497 fnum = SVAL(req->vwv+0, 0);
4498 fsp = file_fsp(req, fnum);
4500 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4505 file_sync_all(conn);
4507 NTSTATUS status = sync_file(conn, fsp, True);
4508 if (!NT_STATUS_IS_OK(status)) {
4509 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4510 fsp->fsp_name, nt_errstr(status) ));
4511 reply_nterror(req, status);
4512 END_PROFILE(SMBflush);
4517 reply_outbuf(req, 0, 0);
4519 DEBUG(3,("flush\n"));
4520 END_PROFILE(SMBflush);
4524 /****************************************************************************
4526 conn POINTER CAN BE NULL HERE !
4527 ****************************************************************************/
4529 void reply_exit(struct smb_request *req)
4531 START_PROFILE(SMBexit);
4533 file_close_pid(req->smbpid, req->vuid);
4535 reply_outbuf(req, 0, 0);
4537 DEBUG(3,("exit\n"));
4539 END_PROFILE(SMBexit);
4543 /****************************************************************************
4544 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4545 ****************************************************************************/
4547 void reply_close(struct smb_request *req)
4549 connection_struct *conn = req->conn;
4550 NTSTATUS status = NT_STATUS_OK;
4551 files_struct *fsp = NULL;
4552 START_PROFILE(SMBclose);
4555 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4556 END_PROFILE(SMBclose);
4560 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4563 * We can only use check_fsp if we know it's not a directory.
4566 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4567 reply_doserror(req, ERRDOS, ERRbadfid);
4568 END_PROFILE(SMBclose);
4572 if(fsp->is_directory) {
4574 * Special case - close NT SMB directory handle.
4576 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4577 status = close_file(req, fsp, NORMAL_CLOSE);
4581 * Close ordinary file.
4584 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4585 fsp->fh->fd, fsp->fnum,
4586 conn->num_files_open));
4589 * Take care of any time sent in the close.
4592 t = srv_make_unix_date3(req->vwv+1);
4593 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4596 * close_file() returns the unix errno if an error
4597 * was detected on close - normally this is due to
4598 * a disk full error. If not then it was probably an I/O error.
4601 status = close_file(req, fsp, NORMAL_CLOSE);
4604 if (!NT_STATUS_IS_OK(status)) {
4605 reply_nterror(req, status);
4606 END_PROFILE(SMBclose);
4610 reply_outbuf(req, 0, 0);
4611 END_PROFILE(SMBclose);
4615 /****************************************************************************
4616 Reply to a writeclose (Core+ protocol).
4617 ****************************************************************************/
4619 void reply_writeclose(struct smb_request *req)
4621 connection_struct *conn = req->conn;
4623 ssize_t nwritten = -1;
4624 NTSTATUS close_status = NT_STATUS_OK;
4627 struct timespec mtime;
4629 struct lock_struct lock;
4631 START_PROFILE(SMBwriteclose);
4634 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4635 END_PROFILE(SMBwriteclose);
4639 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4641 if (!check_fsp(conn, req, fsp)) {
4642 END_PROFILE(SMBwriteclose);
4645 if (!CHECK_WRITE(fsp)) {
4646 reply_doserror(req, ERRDOS,ERRbadaccess);
4647 END_PROFILE(SMBwriteclose);
4651 numtowrite = SVAL(req->vwv+1, 0);
4652 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4653 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4654 data = (const char *)req->buf + 1;
4657 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4658 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4661 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4662 reply_doserror(req, ERRDOS,ERRlock);
4663 END_PROFILE(SMBwriteclose);
4668 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4670 set_close_write_time(fsp, mtime);
4673 * More insanity. W2K only closes the file if writelen > 0.
4678 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4680 close_status = close_file(req, fsp, NORMAL_CLOSE);
4683 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4684 fsp->fnum, (int)numtowrite, (int)nwritten,
4685 conn->num_files_open));
4687 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4688 reply_doserror(req, ERRHRD, ERRdiskfull);
4692 if(!NT_STATUS_IS_OK(close_status)) {
4693 reply_nterror(req, close_status);
4697 reply_outbuf(req, 1, 0);
4699 SSVAL(req->outbuf,smb_vwv0,nwritten);
4703 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4706 END_PROFILE(SMBwriteclose);
4711 #define DBGC_CLASS DBGC_LOCKING
4713 /****************************************************************************
4715 ****************************************************************************/
4717 void reply_lock(struct smb_request *req)
4719 connection_struct *conn = req->conn;
4720 uint64_t count,offset;
4723 struct byte_range_lock *br_lck = NULL;
4725 START_PROFILE(SMBlock);
4728 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4729 END_PROFILE(SMBlock);
4733 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4735 if (!check_fsp(conn, req, fsp)) {
4736 END_PROFILE(SMBlock);
4740 count = (uint64_t)IVAL(req->vwv+1, 0);
4741 offset = (uint64_t)IVAL(req->vwv+3, 0);
4743 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4744 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4746 br_lck = do_lock(smbd_messaging_context(),
4753 False, /* Non-blocking lock. */
4758 TALLOC_FREE(br_lck);
4760 if (NT_STATUS_V(status)) {
4761 reply_nterror(req, status);
4762 END_PROFILE(SMBlock);
4766 reply_outbuf(req, 0, 0);
4768 END_PROFILE(SMBlock);
4772 /****************************************************************************
4774 ****************************************************************************/
4776 void reply_unlock(struct smb_request *req)
4778 connection_struct *conn = req->conn;
4779 uint64_t count,offset;
4783 START_PROFILE(SMBunlock);
4786 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4787 END_PROFILE(SMBunlock);
4791 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4793 if (!check_fsp(conn, req, fsp)) {
4794 END_PROFILE(SMBunlock);
4798 count = (uint64_t)IVAL(req->vwv+1, 0);
4799 offset = (uint64_t)IVAL(req->vwv+3, 0);
4801 status = do_unlock(smbd_messaging_context(),
4808 if (NT_STATUS_V(status)) {
4809 reply_nterror(req, status);
4810 END_PROFILE(SMBunlock);
4814 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4815 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4817 reply_outbuf(req, 0, 0);
4819 END_PROFILE(SMBunlock);
4824 #define DBGC_CLASS DBGC_ALL
4826 /****************************************************************************
4828 conn POINTER CAN BE NULL HERE !
4829 ****************************************************************************/
4831 void reply_tdis(struct smb_request *req)
4833 connection_struct *conn = req->conn;
4834 START_PROFILE(SMBtdis);
4837 DEBUG(4,("Invalid connection in tdis\n"));
4838 reply_doserror(req, ERRSRV, ERRinvnid);
4839 END_PROFILE(SMBtdis);
4845 close_cnum(conn,req->vuid);
4848 reply_outbuf(req, 0, 0);
4849 END_PROFILE(SMBtdis);
4853 /****************************************************************************
4855 conn POINTER CAN BE NULL HERE !
4856 ****************************************************************************/
4858 void reply_echo(struct smb_request *req)
4860 connection_struct *conn = req->conn;
4861 struct smb_perfcount_data local_pcd;
4862 struct smb_perfcount_data *cur_pcd;
4866 START_PROFILE(SMBecho);
4868 smb_init_perfcount_data(&local_pcd);
4871 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4872 END_PROFILE(SMBecho);
4876 smb_reverb = SVAL(req->vwv+0, 0);
4878 reply_outbuf(req, 1, req->buflen);
4880 /* copy any incoming data back out */
4881 if (req->buflen > 0) {
4882 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4885 if (smb_reverb > 100) {
4886 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4890 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4892 /* this makes sure we catch the request pcd */
4893 if (seq_num == smb_reverb) {
4894 cur_pcd = &req->pcd;
4896 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4897 cur_pcd = &local_pcd;
4900 SSVAL(req->outbuf,smb_vwv0,seq_num);
4902 show_msg((char *)req->outbuf);
4903 if (!srv_send_smb(smbd_server_fd(),
4904 (char *)req->outbuf,
4905 true, req->seqnum+1,
4906 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4908 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4911 DEBUG(3,("echo %d times\n", smb_reverb));
4913 TALLOC_FREE(req->outbuf);
4915 END_PROFILE(SMBecho);
4919 /****************************************************************************
4920 Reply to a printopen.
4921 ****************************************************************************/
4923 void reply_printopen(struct smb_request *req)
4925 connection_struct *conn = req->conn;
4927 SMB_STRUCT_STAT sbuf;
4930 START_PROFILE(SMBsplopen);
4933 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4934 END_PROFILE(SMBsplopen);
4938 if (!CAN_PRINT(conn)) {
4939 reply_doserror(req, ERRDOS, ERRnoaccess);
4940 END_PROFILE(SMBsplopen);
4944 status = file_new(req, conn, &fsp);
4945 if(!NT_STATUS_IS_OK(status)) {
4946 reply_nterror(req, status);
4947 END_PROFILE(SMBsplopen);
4951 /* Open for exclusive use, write only. */
4952 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4954 if (!NT_STATUS_IS_OK(status)) {
4955 reply_nterror(req, status);
4956 END_PROFILE(SMBsplopen);
4960 reply_outbuf(req, 1, 0);
4961 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4963 DEBUG(3,("openprint fd=%d fnum=%d\n",
4964 fsp->fh->fd, fsp->fnum));
4966 END_PROFILE(SMBsplopen);
4970 /****************************************************************************
4971 Reply to a printclose.
4972 ****************************************************************************/
4974 void reply_printclose(struct smb_request *req)
4976 connection_struct *conn = req->conn;
4980 START_PROFILE(SMBsplclose);
4983 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4984 END_PROFILE(SMBsplclose);
4988 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4990 if (!check_fsp(conn, req, fsp)) {
4991 END_PROFILE(SMBsplclose);
4995 if (!CAN_PRINT(conn)) {
4996 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4997 END_PROFILE(SMBsplclose);
5001 DEBUG(3,("printclose fd=%d fnum=%d\n",
5002 fsp->fh->fd,fsp->fnum));
5004 status = close_file(req, fsp, NORMAL_CLOSE);
5006 if(!NT_STATUS_IS_OK(status)) {
5007 reply_nterror(req, status);
5008 END_PROFILE(SMBsplclose);
5012 reply_outbuf(req, 0, 0);
5014 END_PROFILE(SMBsplclose);
5018 /****************************************************************************
5019 Reply to a printqueue.
5020 ****************************************************************************/
5022 void reply_printqueue(struct smb_request *req)
5024 connection_struct *conn = req->conn;
5028 START_PROFILE(SMBsplretq);
5031 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5032 END_PROFILE(SMBsplretq);
5036 max_count = SVAL(req->vwv+0, 0);
5037 start_index = SVAL(req->vwv+1, 0);
5039 /* we used to allow the client to get the cnum wrong, but that
5040 is really quite gross and only worked when there was only
5041 one printer - I think we should now only accept it if they
5042 get it right (tridge) */
5043 if (!CAN_PRINT(conn)) {
5044 reply_doserror(req, ERRDOS, ERRnoaccess);
5045 END_PROFILE(SMBsplretq);
5049 reply_outbuf(req, 2, 3);
5050 SSVAL(req->outbuf,smb_vwv0,0);
5051 SSVAL(req->outbuf,smb_vwv1,0);
5052 SCVAL(smb_buf(req->outbuf),0,1);
5053 SSVAL(smb_buf(req->outbuf),1,0);
5055 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5056 start_index, max_count));
5059 print_queue_struct *queue = NULL;
5060 print_status_struct status;
5061 int count = print_queue_status(SNUM(conn), &queue, &status);
5062 int num_to_get = ABS(max_count);
5063 int first = (max_count>0?start_index:start_index+max_count+1);
5069 num_to_get = MIN(num_to_get,count-first);
5072 for (i=first;i<first+num_to_get;i++) {
5076 srv_put_dos_date2(p,0,queue[i].time);
5077 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5078 SSVAL(p,5, queue[i].job);
5079 SIVAL(p,7,queue[i].size);
5081 srvstr_push(blob, req->flags2, p+12,
5082 queue[i].fs_user, 16, STR_ASCII);
5084 if (message_push_blob(
5087 blob, sizeof(blob))) == -1) {
5088 reply_nterror(req, NT_STATUS_NO_MEMORY);
5089 END_PROFILE(SMBsplretq);
5095 SSVAL(req->outbuf,smb_vwv0,count);
5096 SSVAL(req->outbuf,smb_vwv1,
5097 (max_count>0?first+count:first-1));
5098 SCVAL(smb_buf(req->outbuf),0,1);
5099 SSVAL(smb_buf(req->outbuf),1,28*count);
5104 DEBUG(3,("%d entries returned in queue\n",count));
5107 END_PROFILE(SMBsplretq);
5111 /****************************************************************************
5112 Reply to a printwrite.
5113 ****************************************************************************/
5115 void reply_printwrite(struct smb_request *req)
5117 connection_struct *conn = req->conn;
5122 START_PROFILE(SMBsplwr);
5125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5126 END_PROFILE(SMBsplwr);
5130 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5132 if (!check_fsp(conn, req, fsp)) {
5133 END_PROFILE(SMBsplwr);
5137 if (!CAN_PRINT(conn)) {
5138 reply_doserror(req, ERRDOS, ERRnoaccess);
5139 END_PROFILE(SMBsplwr);
5143 if (!CHECK_WRITE(fsp)) {
5144 reply_doserror(req, ERRDOS, ERRbadaccess);
5145 END_PROFILE(SMBsplwr);
5149 numtowrite = SVAL(req->buf, 1);
5151 if (req->buflen < numtowrite + 3) {
5152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5153 END_PROFILE(SMBsplwr);
5157 data = (const char *)req->buf + 3;
5159 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5160 reply_unixerror(req, ERRHRD, ERRdiskfull);
5161 END_PROFILE(SMBsplwr);
5165 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5167 END_PROFILE(SMBsplwr);
5171 /****************************************************************************
5173 ****************************************************************************/
5175 void reply_mkdir(struct smb_request *req)
5177 connection_struct *conn = req->conn;
5178 struct smb_filename *smb_dname = NULL;
5179 char *directory = NULL;
5181 TALLOC_CTX *ctx = talloc_tos();
5183 START_PROFILE(SMBmkdir);
5185 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5186 STR_TERMINATE, &status);
5187 if (!NT_STATUS_IS_OK(status)) {
5188 reply_nterror(req, status);
5192 status = resolve_dfspath(ctx, conn,
5193 req->flags2 & FLAGS2_DFS_PATHNAMES,
5196 if (!NT_STATUS_IS_OK(status)) {
5197 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5198 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5199 ERRSRV, ERRbadpath);
5202 reply_nterror(req, status);
5206 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
5207 if (!NT_STATUS_IS_OK(status)) {
5208 reply_nterror(req, status);
5212 status = get_full_smb_filename(ctx, smb_dname, &directory);
5213 if (!NT_STATUS_IS_OK(status)) {
5214 reply_nterror(req, status);
5218 status = check_name(conn, directory);
5219 if (!NT_STATUS_IS_OK(status)) {
5220 reply_nterror(req, status);
5224 status = create_directory(conn, req, directory);
5226 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5228 if (!NT_STATUS_IS_OK(status)) {
5230 if (!use_nt_status()
5231 && NT_STATUS_EQUAL(status,
5232 NT_STATUS_OBJECT_NAME_COLLISION)) {
5234 * Yes, in the DOS error code case we get a
5235 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5236 * samba4 torture test.
5238 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5241 reply_nterror(req, status);
5245 reply_outbuf(req, 0, 0);
5247 DEBUG( 3, ( "mkdir %s\n", directory ) );
5250 TALLOC_FREE(smb_dname);
5252 END_PROFILE(SMBmkdir);
5256 /****************************************************************************
5257 Static function used by reply_rmdir to delete an entire directory
5258 tree recursively. Return True on ok, False on fail.
5259 ****************************************************************************/
5261 static bool recursive_rmdir(TALLOC_CTX *ctx,
5262 connection_struct *conn,
5265 const char *dname = NULL;
5269 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5275 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5276 char *fullname = NULL;
5278 if (ISDOT(dname) || ISDOTDOT(dname)) {
5282 if (!is_visible_file(conn, directory, dname, &st, False)) {
5286 /* Construct the full name. */
5287 fullname = talloc_asprintf(ctx,
5297 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5302 if(st.st_mode & S_IFDIR) {
5303 if(!recursive_rmdir(ctx, conn, fullname)) {
5307 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5311 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5315 TALLOC_FREE(fullname);
5317 TALLOC_FREE(dir_hnd);
5321 /****************************************************************************
5322 The internals of the rmdir code - called elsewhere.
5323 ****************************************************************************/
5325 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5326 connection_struct *conn,
5327 const char *directory)
5332 /* Might be a symlink. */
5333 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5334 return map_nt_error_from_unix(errno);
5337 if (S_ISLNK(st.st_mode)) {
5338 /* Is what it points to a directory ? */
5339 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5340 return map_nt_error_from_unix(errno);
5342 if (!(S_ISDIR(st.st_mode))) {
5343 return NT_STATUS_NOT_A_DIRECTORY;
5345 ret = SMB_VFS_UNLINK(conn,directory);
5347 ret = SMB_VFS_RMDIR(conn,directory);
5350 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5351 FILE_NOTIFY_CHANGE_DIR_NAME,
5353 return NT_STATUS_OK;
5356 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5358 * Check to see if the only thing in this directory are
5359 * vetoed files/directories. If so then delete them and
5360 * retry. If we fail to delete any of them (and we *don't*
5361 * do a recursive delete) then fail the rmdir.
5365 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5366 directory, NULL, 0);
5368 if(dir_hnd == NULL) {
5373 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5374 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5376 if (!is_visible_file(conn, directory, dname, &st, False))
5378 if(!IS_VETO_PATH(conn, dname)) {
5379 TALLOC_FREE(dir_hnd);
5385 /* We only have veto files/directories.
5386 * Are we allowed to delete them ? */
5388 if(!lp_recursive_veto_delete(SNUM(conn))) {
5389 TALLOC_FREE(dir_hnd);
5394 /* Do a recursive delete. */
5395 RewindDir(dir_hnd,&dirpos);
5396 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5397 char *fullname = NULL;
5399 if (ISDOT(dname) || ISDOTDOT(dname)) {
5402 if (!is_visible_file(conn, directory, dname, &st, False)) {
5406 fullname = talloc_asprintf(ctx,
5416 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5419 if(st.st_mode & S_IFDIR) {
5420 if(!recursive_rmdir(ctx, conn, fullname)) {
5423 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5426 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5429 TALLOC_FREE(fullname);
5431 TALLOC_FREE(dir_hnd);
5432 /* Retry the rmdir */
5433 ret = SMB_VFS_RMDIR(conn,directory);
5439 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5440 "%s\n", directory,strerror(errno)));
5441 return map_nt_error_from_unix(errno);
5444 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5445 FILE_NOTIFY_CHANGE_DIR_NAME,
5448 return NT_STATUS_OK;
5451 /****************************************************************************
5453 ****************************************************************************/
5455 void reply_rmdir(struct smb_request *req)
5457 connection_struct *conn = req->conn;
5458 struct smb_filename *smb_dname = NULL;
5459 char *directory = NULL;
5461 TALLOC_CTX *ctx = talloc_tos();
5463 START_PROFILE(SMBrmdir);
5465 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5466 STR_TERMINATE, &status);
5467 if (!NT_STATUS_IS_OK(status)) {
5468 reply_nterror(req, status);
5472 status = resolve_dfspath(ctx, conn,
5473 req->flags2 & FLAGS2_DFS_PATHNAMES,
5476 if (!NT_STATUS_IS_OK(status)) {
5477 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5478 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5479 ERRSRV, ERRbadpath);
5482 reply_nterror(req, status);
5486 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
5487 if (!NT_STATUS_IS_OK(status)) {
5488 reply_nterror(req, status);
5492 status = get_full_smb_filename(ctx, smb_dname, &directory);
5493 if (!NT_STATUS_IS_OK(status)) {
5494 reply_nterror(req, status);
5498 status = check_name(conn, directory);
5499 if (!NT_STATUS_IS_OK(status)) {
5500 reply_nterror(req, status);
5504 dptr_closepath(directory, req->smbpid);
5505 status = rmdir_internals(ctx, conn, directory);
5506 if (!NT_STATUS_IS_OK(status)) {
5507 reply_nterror(req, status);
5511 reply_outbuf(req, 0, 0);
5513 DEBUG( 3, ( "rmdir %s\n", directory ) );
5516 TALLOC_FREE(smb_dname);
5518 END_PROFILE(SMBrmdir);
5522 /*******************************************************************
5523 Resolve wildcards in a filename rename.
5524 ********************************************************************/
5526 static bool resolve_wildcards(TALLOC_CTX *ctx,
5531 char *name2_copy = NULL;
5536 char *p,*p2, *pname1, *pname2;
5538 name2_copy = talloc_strdup(ctx, name2);
5543 pname1 = strrchr_m(name1,'/');
5544 pname2 = strrchr_m(name2_copy,'/');
5546 if (!pname1 || !pname2) {
5550 /* Truncate the copy of name2 at the last '/' */
5553 /* Now go past the '/' */
5557 root1 = talloc_strdup(ctx, pname1);
5558 root2 = talloc_strdup(ctx, pname2);
5560 if (!root1 || !root2) {
5564 p = strrchr_m(root1,'.');
5567 ext1 = talloc_strdup(ctx, p+1);
5569 ext1 = talloc_strdup(ctx, "");
5571 p = strrchr_m(root2,'.');
5574 ext2 = talloc_strdup(ctx, p+1);
5576 ext2 = talloc_strdup(ctx, "");
5579 if (!ext1 || !ext2) {
5587 /* Hmmm. Should this be mb-aware ? */
5590 } else if (*p2 == '*') {
5592 root2 = talloc_asprintf(ctx, "%s%s",
5611 /* Hmmm. Should this be mb-aware ? */
5614 } else if (*p2 == '*') {
5616 ext2 = talloc_asprintf(ctx, "%s%s",
5632 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5637 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5649 /****************************************************************************
5650 Ensure open files have their names updated. Updated to notify other smbd's
5652 ****************************************************************************/
5654 static void rename_open_files(connection_struct *conn,
5655 struct share_mode_lock *lck,
5656 const char *newname)
5659 bool did_rename = False;
5661 for(fsp = file_find_di_first(lck->id); fsp;
5662 fsp = file_find_di_next(fsp)) {
5663 /* fsp_name is a relative path under the fsp. To change this for other
5664 sharepaths we need to manipulate relative paths. */
5665 /* TODO - create the absolute path and manipulate the newname
5666 relative to the sharepath. */
5667 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5670 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5671 fsp->fnum, file_id_string_tos(&fsp->file_id),
5672 fsp->fsp_name, newname ));
5673 string_set(&fsp->fsp_name, newname);
5678 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5679 file_id_string_tos(&lck->id), newname ));
5682 /* Send messages to all smbd's (not ourself) that the name has changed. */
5683 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5687 /****************************************************************************
5688 We need to check if the source path is a parent directory of the destination
5689 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5690 refuse the rename with a sharing violation. Under UNIX the above call can
5691 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5692 probably need to check that the client is a Windows one before disallowing
5693 this as a UNIX client (one with UNIX extensions) can know the source is a
5694 symlink and make this decision intelligently. Found by an excellent bug
5695 report from <AndyLiebman@aol.com>.
5696 ****************************************************************************/
5698 static bool rename_path_prefix_equal(const char *src, const char *dest)
5700 const char *psrc = src;
5701 const char *pdst = dest;
5704 if (psrc[0] == '.' && psrc[1] == '/') {
5707 if (pdst[0] == '.' && pdst[1] == '/') {
5710 if ((slen = strlen(psrc)) > strlen(pdst)) {
5713 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5717 * Do the notify calls from a rename
5720 static void notify_rename(connection_struct *conn, bool is_dir,
5721 const char *oldpath, const char *newpath)
5723 char *olddir, *newdir;
5724 const char *oldname, *newname;
5727 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5728 : FILE_NOTIFY_CHANGE_FILE_NAME;
5730 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5731 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5732 TALLOC_FREE(olddir);
5736 if (strcmp(olddir, newdir) == 0) {
5737 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5738 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5741 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5742 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5744 TALLOC_FREE(olddir);
5745 TALLOC_FREE(newdir);
5747 /* this is a strange one. w2k3 gives an additional event for
5748 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5749 files, but not directories */
5751 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5752 FILE_NOTIFY_CHANGE_ATTRIBUTES
5753 |FILE_NOTIFY_CHANGE_CREATION,
5758 /****************************************************************************
5759 Rename an open file - given an fsp.
5760 ****************************************************************************/
5762 NTSTATUS rename_internals_fsp(connection_struct *conn,
5765 const char *newname_last_component,
5767 bool replace_if_exists)
5769 TALLOC_CTX *ctx = talloc_tos();
5770 SMB_STRUCT_STAT sbuf, sbuf1;
5771 NTSTATUS status = NT_STATUS_OK;
5772 struct share_mode_lock *lck = NULL;
5773 bool dst_exists, old_is_stream, new_is_stream;
5777 status = check_name(conn, newname);
5778 if (!NT_STATUS_IS_OK(status)) {
5782 /* Ensure newname contains a '/' */
5783 if(strrchr_m(newname,'/') == 0) {
5784 newname = talloc_asprintf(ctx,
5788 return NT_STATUS_NO_MEMORY;
5793 * Check for special case with case preserving and not
5794 * case sensitive. If the old last component differs from the original
5795 * last component only by case, then we should allow
5796 * the rename (user is trying to change the case of the
5800 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5801 strequal(newname, fsp->fsp_name)) {
5803 char *newname_modified_last_component = NULL;
5806 * Get the last component of the modified name.
5807 * Note that we guarantee that newname contains a '/'
5810 p = strrchr_m(newname,'/');
5811 newname_modified_last_component = talloc_strdup(ctx,
5813 if (!newname_modified_last_component) {
5814 return NT_STATUS_NO_MEMORY;
5817 if(strcsequal(newname_modified_last_component,
5818 newname_last_component) == False) {
5820 * Replace the modified last component with
5823 *p = '\0'; /* Truncate at the '/' */
5824 newname = talloc_asprintf(ctx,
5827 newname_last_component);
5832 * If the src and dest names are identical - including case,
5833 * don't do the rename, just return success.
5836 if (strcsequal(fsp->fsp_name, newname)) {
5837 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5839 return NT_STATUS_OK;
5842 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5843 new_is_stream = is_ntfs_stream_name(newname);
5845 /* Return the correct error code if both names aren't streams. */
5846 if (!old_is_stream && new_is_stream) {
5847 return NT_STATUS_OBJECT_NAME_INVALID;
5850 if (old_is_stream && !new_is_stream) {
5851 return NT_STATUS_INVALID_PARAMETER;
5855 * Have vfs_object_exist also fill sbuf1
5857 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5859 if(!replace_if_exists && dst_exists) {
5860 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5861 fsp->fsp_name,newname));
5862 return NT_STATUS_OBJECT_NAME_COLLISION;
5866 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5867 files_struct *dst_fsp = file_find_di_first(fileid);
5868 /* The file can be open when renaming a stream */
5869 if (dst_fsp && !new_is_stream) {
5870 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5871 return NT_STATUS_ACCESS_DENIED;
5875 /* Ensure we have a valid stat struct for the source. */
5876 if (fsp->fh->fd != -1) {
5877 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5878 return map_nt_error_from_unix(errno);
5882 if (fsp->posix_open) {
5883 ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
5885 ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
5888 return map_nt_error_from_unix(errno);
5892 status = can_rename(conn, fsp, attrs, &sbuf);
5894 if (!NT_STATUS_IS_OK(status)) {
5895 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5896 nt_errstr(status), fsp->fsp_name,newname));
5897 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5898 status = NT_STATUS_ACCESS_DENIED;
5902 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5903 return NT_STATUS_ACCESS_DENIED;
5906 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5910 * We have the file open ourselves, so not being able to get the
5911 * corresponding share mode lock is a fatal error.
5914 SMB_ASSERT(lck != NULL);
5916 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5917 uint32 create_options = fsp->fh->private_options;
5919 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5920 fsp->fsp_name,newname));
5922 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5924 rename_open_files(conn, lck, newname);
5927 * A rename acts as a new file create w.r.t. allowing an initial delete
5928 * on close, probably because in Windows there is a new handle to the
5929 * new file. If initial delete on close was requested but not
5930 * originally set, we need to set it here. This is probably not 100% correct,
5931 * but will work for the CIFSFS client which in non-posix mode
5932 * depends on these semantics. JRA.
5935 if (create_options & FILE_DELETE_ON_CLOSE) {
5936 status = can_set_delete_on_close(fsp, True, 0);
5938 if (NT_STATUS_IS_OK(status)) {
5939 /* Note that here we set the *inital* delete on close flag,
5940 * not the regular one. The magic gets handled in close. */
5941 fsp->initial_delete_on_close = True;
5945 return NT_STATUS_OK;
5950 if (errno == ENOTDIR || errno == EISDIR) {
5951 status = NT_STATUS_OBJECT_NAME_COLLISION;
5953 status = map_nt_error_from_unix(errno);
5956 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5957 nt_errstr(status), fsp->fsp_name,newname));
5962 /****************************************************************************
5963 The guts of the rename command, split out so it may be called by the NT SMB
5965 ****************************************************************************/
5967 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5968 connection_struct *conn,
5969 struct smb_request *req,
5970 const char *name_in,
5971 const char *newname_in,
5973 bool replace_if_exists,
5976 uint32_t access_mask)
5978 struct smb_filename *smb_fname = NULL;
5979 struct smb_filename *smb_fname_new = NULL;
5980 char *directory = NULL;
5983 char *newname = NULL;
5986 NTSTATUS status = NT_STATUS_OK;
5987 struct smb_Dir *dir_hnd = NULL;
5990 int create_options = 0;
5991 bool posix_pathnames = lp_posix_pathnames();
5993 status = unix_convert(ctx, conn, name_in, &smb_fname,
5994 src_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
5995 if (!NT_STATUS_IS_OK(status)) {
5999 status = get_full_smb_filename(ctx, smb_fname, &name);
6000 if (!NT_STATUS_IS_OK(status)) {
6004 status = unix_convert(ctx, conn, newname_in, &smb_fname_new,
6006 (dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0)));
6007 if (!NT_STATUS_IS_OK(status)) {
6011 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
6012 if (!NT_STATUS_IS_OK(status)) {
6017 * Split the old name into directory and last component
6018 * strings. Note that unix_convert may have stripped off a
6019 * leading ./ from both name and newname if the rename is
6020 * at the root of the share. We need to make sure either both
6021 * name and newname contain a / character or neither of them do
6022 * as this is checked in resolve_wildcards().
6025 p = strrchr_m(name,'/');
6027 directory = talloc_strdup(ctx, ".");
6029 status = NT_STATUS_NO_MEMORY;
6035 directory = talloc_strdup(ctx, name);
6037 status = NT_STATUS_NO_MEMORY;
6041 *p = '/'; /* Replace needed for exceptional test below. */
6045 * We should only check the mangled cache
6046 * here if unix_convert failed. This means
6047 * that the path in 'mask' doesn't exist
6048 * on the file system and so we need to look
6049 * for a possible mangle. This patch from
6050 * Tine Smukavec <valentin.smukavec@hermes.si>.
6053 if (!VALID_STAT(smb_fname->st) && mangle_is_mangled(mask, conn->params)) {
6054 char *new_mask = NULL;
6055 mangle_lookup_name_from_8_3(ctx,
6064 if (!src_has_wild) {
6068 * No wildcards - just process the one file.
6070 /* Add a terminating '/' to the directory name. */
6071 directory = talloc_asprintf_append(directory,
6075 status = NT_STATUS_NO_MEMORY;
6079 /* Ensure newname contains a '/' also */
6080 if(strrchr_m(newname,'/') == 0) {
6081 newname = talloc_asprintf(ctx,
6085 status = NT_STATUS_NO_MEMORY;
6090 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6091 "case_preserve = %d, short case preserve = %d, "
6092 "directory = %s, newname = %s, "
6093 "last_component_dest = %s\n",
6094 conn->case_sensitive, conn->case_preserve,
6095 conn->short_case_preserve, directory,
6096 newname, smb_fname_new->original_lcomp));
6098 /* The dest name still may have wildcards. */
6099 if (dest_has_wild) {
6100 char *mod_newname = NULL;
6101 if (!resolve_wildcards(ctx,
6102 directory,newname,&mod_newname)) {
6103 DEBUG(6, ("rename_internals: resolve_wildcards "
6107 status = NT_STATUS_NO_MEMORY;
6110 newname = mod_newname;
6113 ZERO_STRUCT(smb_fname->st);
6114 if (posix_pathnames) {
6115 SMB_VFS_LSTAT(conn, directory, &smb_fname->st);
6117 SMB_VFS_STAT(conn, directory, &smb_fname->st);
6120 if (S_ISDIR(smb_fname->st.st_mode)) {
6121 create_options |= FILE_DIRECTORY_FILE;
6124 status = SMB_VFS_CREATE_FILE(
6127 0, /* root_dir_fid */
6128 directory, /* fname */
6129 0, /* create_file_flags */
6130 access_mask, /* access_mask */
6131 (FILE_SHARE_READ | /* share_access */
6133 FILE_OPEN, /* create_disposition*/
6134 create_options, /* create_options */
6135 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6136 0, /* oplock_request */
6137 0, /* allocation_size */
6142 &smb_fname->st); /* psbuf */
6144 if (!NT_STATUS_IS_OK(status)) {
6145 DEBUG(3, ("Could not open rename source %s: %s\n",
6146 directory, nt_errstr(status)));
6150 status = rename_internals_fsp(conn, fsp, newname,
6151 smb_fname_new->original_lcomp,
6152 attrs, replace_if_exists);
6154 close_file(req, fsp, NORMAL_CLOSE);
6156 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6157 nt_errstr(status), directory,newname));
6163 * Wildcards - process each file that matches.
6165 if (strequal(mask,"????????.???")) {
6170 status = check_name(conn, directory);
6171 if (!NT_STATUS_IS_OK(status)) {
6175 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
6176 if (dir_hnd == NULL) {
6177 status = map_nt_error_from_unix(errno);
6181 status = NT_STATUS_NO_SUCH_FILE;
6183 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6184 * - gentest fix. JRA
6187 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname->st))) {
6188 files_struct *fsp = NULL;
6190 char *destname = NULL;
6191 bool sysdir_entry = False;
6193 /* Quick check for "." and ".." */
6194 if (ISDOT(dname) || ISDOTDOT(dname)) {
6196 sysdir_entry = True;
6202 if (!is_visible_file(conn, directory, dname, &smb_fname->st,
6207 if(!mask_match(dname, mask, conn->case_sensitive)) {
6212 status = NT_STATUS_OBJECT_NAME_INVALID;
6216 fname = talloc_asprintf(ctx,
6221 status = NT_STATUS_NO_MEMORY;
6225 if (!resolve_wildcards(ctx,
6226 fname,newname,&destname)) {
6227 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6233 status = NT_STATUS_NO_MEMORY;
6237 ZERO_STRUCT(smb_fname->st);
6238 if (posix_pathnames) {
6239 SMB_VFS_LSTAT(conn, fname, &smb_fname->st);
6241 SMB_VFS_STAT(conn, fname, &smb_fname->st);
6246 if (S_ISDIR(smb_fname->st.st_mode)) {
6247 create_options |= FILE_DIRECTORY_FILE;
6250 status = SMB_VFS_CREATE_FILE(
6253 0, /* root_dir_fid */
6255 0, /* create_file_flags */
6256 access_mask, /* access_mask */
6257 (FILE_SHARE_READ | /* share_access */
6259 FILE_OPEN, /* create_disposition*/
6260 create_options, /* create_options */
6261 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6262 0, /* oplock_request */
6263 0, /* allocation_size */
6268 &smb_fname->st); /* psbuf */
6270 if (!NT_STATUS_IS_OK(status)) {
6271 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6272 "returned %s rename %s -> %s\n",
6273 nt_errstr(status), directory, newname));
6277 status = rename_internals_fsp(conn, fsp, destname, dname,
6278 attrs, replace_if_exists);
6280 close_file(req, fsp, NORMAL_CLOSE);
6282 if (!NT_STATUS_IS_OK(status)) {
6283 DEBUG(3, ("rename_internals_fsp returned %s for "
6284 "rename %s -> %s\n", nt_errstr(status),
6285 directory, newname));
6291 DEBUG(3,("rename_internals: doing rename on %s -> "
6292 "%s\n",fname,destname));
6295 TALLOC_FREE(destname);
6297 TALLOC_FREE(dir_hnd);
6299 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6300 status = map_nt_error_from_unix(errno);
6305 TALLOC_FREE(smb_fname);
6307 if (smb_fname_new) {
6308 TALLOC_FREE(smb_fname_new);
6313 /****************************************************************************
6315 ****************************************************************************/
6317 void reply_mv(struct smb_request *req)
6319 connection_struct *conn = req->conn;
6321 char *newname = NULL;
6325 bool src_has_wcard = False;
6326 bool dest_has_wcard = False;
6327 TALLOC_CTX *ctx = talloc_tos();
6329 START_PROFILE(SMBmv);
6332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6337 attrs = SVAL(req->vwv+0, 0);
6339 p = (const char *)req->buf + 1;
6340 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6341 &status, &src_has_wcard);
6342 if (!NT_STATUS_IS_OK(status)) {
6343 reply_nterror(req, status);
6348 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6349 &status, &dest_has_wcard);
6350 if (!NT_STATUS_IS_OK(status)) {
6351 reply_nterror(req, status);
6356 status = resolve_dfspath_wcard(ctx, conn,
6357 req->flags2 & FLAGS2_DFS_PATHNAMES,
6361 if (!NT_STATUS_IS_OK(status)) {
6362 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6363 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6364 ERRSRV, ERRbadpath);
6368 reply_nterror(req, status);
6373 status = resolve_dfspath_wcard(ctx, conn,
6374 req->flags2 & FLAGS2_DFS_PATHNAMES,
6378 if (!NT_STATUS_IS_OK(status)) {
6379 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6380 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6381 ERRSRV, ERRbadpath);
6385 reply_nterror(req, status);
6390 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6392 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6393 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6394 if (!NT_STATUS_IS_OK(status)) {
6395 if (open_was_deferred(req->mid)) {
6396 /* We have re-scheduled this call. */
6400 reply_nterror(req, status);
6405 reply_outbuf(req, 0, 0);
6411 /*******************************************************************
6412 Copy a file as part of a reply_copy.
6413 ******************************************************************/
6416 * TODO: check error codes on all callers
6419 NTSTATUS copy_file(TALLOC_CTX *ctx,
6420 connection_struct *conn,
6425 bool target_is_directory)
6427 SMB_STRUCT_STAT src_sbuf, sbuf2;
6429 files_struct *fsp1,*fsp2;
6432 uint32 new_create_disposition;
6435 dest = talloc_strdup(ctx, dest1);
6437 return NT_STATUS_NO_MEMORY;
6439 if (target_is_directory) {
6440 const char *p = strrchr_m(src,'/');
6446 dest = talloc_asprintf_append(dest,
6450 return NT_STATUS_NO_MEMORY;
6454 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6456 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6459 if (!target_is_directory && count) {
6460 new_create_disposition = FILE_OPEN;
6462 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6463 NULL, NULL, &new_create_disposition, NULL)) {
6465 return NT_STATUS_INVALID_PARAMETER;
6469 status = SMB_VFS_CREATE_FILE(
6472 0, /* root_dir_fid */
6474 0, /* create_file_flags */
6475 FILE_GENERIC_READ, /* access_mask */
6476 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6477 FILE_OPEN, /* create_disposition*/
6478 0, /* create_options */
6479 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6480 INTERNAL_OPEN_ONLY, /* oplock_request */
6481 0, /* allocation_size */
6486 &src_sbuf); /* psbuf */
6488 if (!NT_STATUS_IS_OK(status)) {
6493 dosattrs = dos_mode(conn, src, &src_sbuf);
6494 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6495 ZERO_STRUCTP(&sbuf2);
6498 status = SMB_VFS_CREATE_FILE(
6501 0, /* root_dir_fid */
6503 0, /* create_file_flags */
6504 FILE_GENERIC_WRITE, /* access_mask */
6505 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6506 new_create_disposition, /* create_disposition*/
6507 0, /* create_options */
6508 dosattrs, /* file_attributes */
6509 INTERNAL_OPEN_ONLY, /* oplock_request */
6510 0, /* allocation_size */
6515 &sbuf2); /* psbuf */
6519 if (!NT_STATUS_IS_OK(status)) {
6520 close_file(NULL, fsp1, ERROR_CLOSE);
6524 if ((ofun&3) == 1) {
6525 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6526 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6528 * Stop the copy from occurring.
6531 src_sbuf.st_size = 0;
6535 if (src_sbuf.st_size) {
6536 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6539 close_file(NULL, fsp1, NORMAL_CLOSE);
6541 /* Ensure the modtime is set correctly on the destination file. */
6542 set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
6545 * As we are opening fsp1 read-only we only expect
6546 * an error on close on fsp2 if we are out of space.
6547 * Thus we don't look at the error return from the
6550 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6552 if (!NT_STATUS_IS_OK(status)) {
6556 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6557 return NT_STATUS_DISK_FULL;
6560 return NT_STATUS_OK;
6563 /****************************************************************************
6564 Reply to a file copy.
6565 ****************************************************************************/
6567 void reply_copy(struct smb_request *req)
6569 connection_struct *conn = req->conn;
6570 struct smb_filename *smb_fname = NULL;
6571 struct smb_filename *smb_fname_new = NULL;
6573 char *newname = NULL;
6574 char *directory = NULL;
6575 const char *mask = NULL;
6576 const char mask_star[] = "*";
6579 int error = ERRnoaccess;
6584 bool target_is_directory=False;
6585 bool source_has_wild = False;
6586 bool dest_has_wild = False;
6588 TALLOC_CTX *ctx = talloc_tos();
6590 START_PROFILE(SMBcopy);
6593 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6597 tid2 = SVAL(req->vwv+0, 0);
6598 ofun = SVAL(req->vwv+1, 0);
6599 flags = SVAL(req->vwv+2, 0);
6601 p = (const char *)req->buf;
6602 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6603 &status, &source_has_wild);
6604 if (!NT_STATUS_IS_OK(status)) {
6605 reply_nterror(req, status);
6608 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6609 &status, &dest_has_wild);
6610 if (!NT_STATUS_IS_OK(status)) {
6611 reply_nterror(req, status);
6615 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6617 if (tid2 != conn->cnum) {
6618 /* can't currently handle inter share copies XXXX */
6619 DEBUG(3,("Rejecting inter-share copy\n"));
6620 reply_doserror(req, ERRSRV, ERRinvdevice);
6624 status = resolve_dfspath_wcard(ctx, conn,
6625 req->flags2 & FLAGS2_DFS_PATHNAMES,
6629 if (!NT_STATUS_IS_OK(status)) {
6630 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6631 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6632 ERRSRV, ERRbadpath);
6635 reply_nterror(req, status);
6639 status = resolve_dfspath_wcard(ctx, conn,
6640 req->flags2 & FLAGS2_DFS_PATHNAMES,
6644 if (!NT_STATUS_IS_OK(status)) {
6645 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6646 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6647 ERRSRV, ERRbadpath);
6650 reply_nterror(req, status);
6654 status = unix_convert(ctx, conn, name, &smb_fname,
6655 source_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6656 if (!NT_STATUS_IS_OK(status)) {
6657 reply_nterror(req, status);
6661 status = get_full_smb_filename(ctx, smb_fname, &name);
6662 if (!NT_STATUS_IS_OK(status)) {
6663 reply_nterror(req, status);
6667 status = unix_convert(ctx, conn, newname, &smb_fname_new,
6668 dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6669 if (!NT_STATUS_IS_OK(status)) {
6670 reply_nterror(req, status);
6674 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
6675 if (!NT_STATUS_IS_OK(status)) {
6676 reply_nterror(req, status);
6680 target_is_directory = VALID_STAT_OF_DIR(smb_fname_new->st);
6682 if ((flags&1) && target_is_directory) {
6683 reply_doserror(req, ERRDOS, ERRbadfile);
6687 if ((flags&2) && !target_is_directory) {
6688 reply_doserror(req, ERRDOS, ERRbadpath);
6692 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname->st)) {
6693 /* wants a tree copy! XXXX */
6694 DEBUG(3,("Rejecting tree copy\n"));
6695 reply_doserror(req, ERRSRV, ERRerror);
6699 p = strrchr_m(name,'/');
6701 directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
6704 directory = talloc_strdup(ctx, "./");
6709 reply_nterror(req, NT_STATUS_NO_MEMORY);
6714 * We should only check the mangled cache
6715 * here if unix_convert failed. This means
6716 * that the path in 'mask' doesn't exist
6717 * on the file system and so we need to look
6718 * for a possible mangle. This patch from
6719 * Tine Smukavec <valentin.smukavec@hermes.si>.
6722 if (!VALID_STAT(smb_fname->st) &&
6723 mangle_is_mangled(mask, conn->params)) {
6724 char *new_mask = NULL;
6725 mangle_lookup_name_from_8_3(ctx,
6734 if (!source_has_wild) {
6735 directory = talloc_asprintf_append(directory,
6738 if (dest_has_wild) {
6739 char *mod_newname = NULL;
6740 if (!resolve_wildcards(ctx,
6741 directory,newname,&mod_newname)) {
6742 reply_nterror(req, NT_STATUS_NO_MEMORY);
6745 newname = mod_newname;
6748 status = check_name(conn, directory);
6749 if (!NT_STATUS_IS_OK(status)) {
6750 reply_nterror(req, status);
6754 status = check_name(conn, newname);
6755 if (!NT_STATUS_IS_OK(status)) {
6756 reply_nterror(req, status);
6760 status = copy_file(ctx,conn,directory,newname,ofun,
6761 count,target_is_directory);
6763 if(!NT_STATUS_IS_OK(status)) {
6764 reply_nterror(req, status);
6770 struct smb_Dir *dir_hnd = NULL;
6771 const char *dname = NULL;
6774 if (strequal(mask,"????????.???")) {
6778 status = check_name(conn, directory);
6779 if (!NT_STATUS_IS_OK(status)) {
6780 reply_nterror(req, status);
6784 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6785 if (dir_hnd == NULL) {
6786 status = map_nt_error_from_unix(errno);
6787 reply_nterror(req, status);
6793 while ((dname = ReadDirName(dir_hnd, &offset,
6795 char *destname = NULL;
6798 if (ISDOT(dname) || ISDOTDOT(dname)) {
6802 if (!is_visible_file(conn, directory, dname,
6803 &smb_fname->st, False)) {
6807 if(!mask_match(dname, mask, conn->case_sensitive)) {
6811 error = ERRnoaccess;
6812 fname = talloc_asprintf(ctx,
6817 TALLOC_FREE(dir_hnd);
6818 reply_nterror(req, NT_STATUS_NO_MEMORY);
6822 if (!resolve_wildcards(ctx,
6823 fname,newname,&destname)) {
6827 TALLOC_FREE(dir_hnd);
6828 reply_nterror(req, NT_STATUS_NO_MEMORY);
6832 status = check_name(conn, fname);
6833 if (!NT_STATUS_IS_OK(status)) {
6834 TALLOC_FREE(dir_hnd);
6835 reply_nterror(req, status);
6839 status = check_name(conn, destname);
6840 if (!NT_STATUS_IS_OK(status)) {
6841 TALLOC_FREE(dir_hnd);
6842 reply_nterror(req, status);
6846 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6848 status = copy_file(ctx,conn,fname,destname,ofun,
6849 count,target_is_directory);
6850 if (NT_STATUS_IS_OK(status)) {
6854 TALLOC_FREE(destname);
6856 TALLOC_FREE(dir_hnd);
6861 /* Error on close... */
6863 reply_unixerror(req, ERRHRD, ERRgeneral);
6867 reply_doserror(req, ERRDOS, error);
6871 reply_outbuf(req, 1, 0);
6872 SSVAL(req->outbuf,smb_vwv0,count);
6875 TALLOC_FREE(smb_fname);
6877 if (smb_fname_new) {
6878 TALLOC_FREE(smb_fname_new);
6880 END_PROFILE(SMBcopy);
6885 #define DBGC_CLASS DBGC_LOCKING
6887 /****************************************************************************
6888 Get a lock pid, dealing with large count requests.
6889 ****************************************************************************/
6891 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6892 bool large_file_format)
6894 if(!large_file_format)
6895 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6897 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6900 /****************************************************************************
6901 Get a lock count, dealing with large count requests.
6902 ****************************************************************************/
6904 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6905 bool large_file_format)
6909 if(!large_file_format) {
6910 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6913 #if defined(HAVE_LONGLONG)
6914 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6915 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6916 #else /* HAVE_LONGLONG */
6919 * NT4.x seems to be broken in that it sends large file (64 bit)
6920 * lockingX calls even if the CAP_LARGE_FILES was *not*
6921 * negotiated. For boxes without large unsigned ints truncate the
6922 * lock count by dropping the top 32 bits.
6925 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6926 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6927 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6928 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6929 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6932 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6933 #endif /* HAVE_LONGLONG */
6939 #if !defined(HAVE_LONGLONG)
6940 /****************************************************************************
6941 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6942 ****************************************************************************/
6944 static uint32 map_lock_offset(uint32 high, uint32 low)
6948 uint32 highcopy = high;
6951 * Try and find out how many significant bits there are in high.
6954 for(i = 0; highcopy; i++)
6958 * We use 31 bits not 32 here as POSIX
6959 * lock offsets may not be negative.
6962 mask = (~0) << (31 - i);
6965 return 0; /* Fail. */
6971 #endif /* !defined(HAVE_LONGLONG) */
6973 /****************************************************************************
6974 Get a lock offset, dealing with large offset requests.
6975 ****************************************************************************/
6977 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6978 bool large_file_format, bool *err)
6980 uint64_t offset = 0;
6984 if(!large_file_format) {
6985 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6988 #if defined(HAVE_LONGLONG)
6989 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6990 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6991 #else /* HAVE_LONGLONG */
6994 * NT4.x seems to be broken in that it sends large file (64 bit)
6995 * lockingX calls even if the CAP_LARGE_FILES was *not*
6996 * negotiated. For boxes without large unsigned ints mangle the
6997 * lock offset by mapping the top 32 bits onto the lower 32.
7000 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7001 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7002 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7005 if((new_low = map_lock_offset(high, low)) == 0) {
7007 return (uint64_t)-1;
7010 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7011 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7012 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7013 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7016 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7017 #endif /* HAVE_LONGLONG */
7023 /****************************************************************************
7024 Reply to a lockingX request.
7025 ****************************************************************************/
7027 void reply_lockingX(struct smb_request *req)
7029 connection_struct *conn = req->conn;
7031 unsigned char locktype;
7032 unsigned char oplocklevel;
7035 uint64_t count = 0, offset = 0;
7039 const uint8_t *data;
7040 bool large_file_format;
7042 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7044 START_PROFILE(SMBlockingX);
7047 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7048 END_PROFILE(SMBlockingX);
7052 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7053 locktype = CVAL(req->vwv+3, 0);
7054 oplocklevel = CVAL(req->vwv+3, 1);
7055 num_ulocks = SVAL(req->vwv+6, 0);
7056 num_locks = SVAL(req->vwv+7, 0);
7057 lock_timeout = IVAL(req->vwv+4, 0);
7058 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7060 if (!check_fsp(conn, req, fsp)) {
7061 END_PROFILE(SMBlockingX);
7067 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7068 /* we don't support these - and CANCEL_LOCK makes w2k
7069 and XP reboot so I don't really want to be
7070 compatible! (tridge) */
7071 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7072 END_PROFILE(SMBlockingX);
7076 /* Check if this is an oplock break on a file
7077 we have granted an oplock on.
7079 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7080 /* Client can insist on breaking to none. */
7081 bool break_to_none = (oplocklevel == 0);
7084 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7085 "for fnum = %d\n", (unsigned int)oplocklevel,
7089 * Make sure we have granted an exclusive or batch oplock on
7093 if (fsp->oplock_type == 0) {
7095 /* The Samba4 nbench simulator doesn't understand
7096 the difference between break to level2 and break
7097 to none from level2 - it sends oplock break
7098 replies in both cases. Don't keep logging an error
7099 message here - just ignore it. JRA. */
7101 DEBUG(5,("reply_lockingX: Error : oplock break from "
7102 "client for fnum = %d (oplock=%d) and no "
7103 "oplock granted on this file (%s).\n",
7104 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
7106 /* if this is a pure oplock break request then don't
7108 if (num_locks == 0 && num_ulocks == 0) {
7109 END_PROFILE(SMBlockingX);
7112 END_PROFILE(SMBlockingX);
7113 reply_doserror(req, ERRDOS, ERRlock);
7118 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7120 result = remove_oplock(fsp);
7122 result = downgrade_oplock(fsp);
7126 DEBUG(0, ("reply_lockingX: error in removing "
7127 "oplock on file %s\n", fsp->fsp_name));
7128 /* Hmmm. Is this panic justified? */
7129 smb_panic("internal tdb error");
7132 reply_to_oplock_break_requests(fsp);
7134 /* if this is a pure oplock break request then don't send a
7136 if (num_locks == 0 && num_ulocks == 0) {
7137 /* Sanity check - ensure a pure oplock break is not a
7139 if(CVAL(req->vwv+0, 0) != 0xff)
7140 DEBUG(0,("reply_lockingX: Error : pure oplock "
7141 "break is a chained %d request !\n",
7142 (unsigned int)CVAL(req->vwv+0, 0)));
7143 END_PROFILE(SMBlockingX);
7149 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7150 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7151 END_PROFILE(SMBlockingX);
7155 /* Data now points at the beginning of the list
7156 of smb_unlkrng structs */
7157 for(i = 0; i < (int)num_ulocks; i++) {
7158 lock_pid = get_lock_pid( data, i, large_file_format);
7159 count = get_lock_count( data, i, large_file_format);
7160 offset = get_lock_offset( data, i, large_file_format, &err);
7163 * There is no error code marked "stupid client bug".... :-).
7166 END_PROFILE(SMBlockingX);
7167 reply_doserror(req, ERRDOS, ERRnoaccess);
7171 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
7172 "pid %u, file %s\n", (double)offset, (double)count,
7173 (unsigned int)lock_pid, fsp->fsp_name ));
7175 status = do_unlock(smbd_messaging_context(),
7182 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
7183 nt_errstr(status)));
7185 if (NT_STATUS_V(status)) {
7186 END_PROFILE(SMBlockingX);
7187 reply_nterror(req, status);
7192 /* Setup the timeout in seconds. */
7194 if (!lp_blocking_locks(SNUM(conn))) {
7198 /* Now do any requested locks */
7199 data += ((large_file_format ? 20 : 10)*num_ulocks);
7201 /* Data now points at the beginning of the list
7202 of smb_lkrng structs */
7204 for(i = 0; i < (int)num_locks; i++) {
7205 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
7206 READ_LOCK:WRITE_LOCK);
7207 lock_pid = get_lock_pid( data, i, large_file_format);
7208 count = get_lock_count( data, i, large_file_format);
7209 offset = get_lock_offset( data, i, large_file_format, &err);
7212 * There is no error code marked "stupid client bug".... :-).
7215 END_PROFILE(SMBlockingX);
7216 reply_doserror(req, ERRDOS, ERRnoaccess);
7220 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
7221 "%u, file %s timeout = %d\n", (double)offset,
7222 (double)count, (unsigned int)lock_pid,
7223 fsp->fsp_name, (int)lock_timeout ));
7225 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7226 struct blocking_lock_record *blr = NULL;
7228 if (lp_blocking_locks(SNUM(conn))) {
7230 /* Schedule a message to ourselves to
7231 remove the blocking lock record and
7232 return the right error. */
7234 blr = blocking_lock_cancel(fsp,
7240 NT_STATUS_FILE_LOCK_CONFLICT);
7242 END_PROFILE(SMBlockingX);
7247 ERRcancelviolation));
7251 /* Remove a matching pending lock. */
7252 status = do_lock_cancel(fsp,
7259 bool blocking_lock = lock_timeout ? True : False;
7260 bool defer_lock = False;
7261 struct byte_range_lock *br_lck;
7262 uint32 block_smbpid;
7264 br_lck = do_lock(smbd_messaging_context(),
7276 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7277 /* Windows internal resolution for blocking locks seems
7278 to be about 200ms... Don't wait for less than that. JRA. */
7279 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7280 lock_timeout = lp_lock_spin_time();
7285 /* This heuristic seems to match W2K3 very well. If a
7286 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7287 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7288 far as I can tell. Replacement for do_lock_spin(). JRA. */
7290 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7291 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7293 lock_timeout = lp_lock_spin_time();
7296 if (br_lck && defer_lock) {
7298 * A blocking lock was requested. Package up
7299 * this smb into a queued request and push it
7300 * onto the blocking lock queue.
7302 if(push_blocking_lock_request(br_lck,
7313 TALLOC_FREE(br_lck);
7314 END_PROFILE(SMBlockingX);
7319 TALLOC_FREE(br_lck);
7322 if (NT_STATUS_V(status)) {
7323 END_PROFILE(SMBlockingX);
7324 reply_nterror(req, status);
7329 /* If any of the above locks failed, then we must unlock
7330 all of the previous locks (X/Open spec). */
7332 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7336 * Ensure we don't do a remove on the lock that just failed,
7337 * as under POSIX rules, if we have a lock already there, we
7338 * will delete it (and we shouldn't) .....
7340 for(i--; i >= 0; i--) {
7341 lock_pid = get_lock_pid( data, i, large_file_format);
7342 count = get_lock_count( data, i, large_file_format);
7343 offset = get_lock_offset( data, i, large_file_format,
7347 * There is no error code marked "stupid client
7351 END_PROFILE(SMBlockingX);
7352 reply_doserror(req, ERRDOS, ERRnoaccess);
7356 do_unlock(smbd_messaging_context(),
7363 END_PROFILE(SMBlockingX);
7364 reply_nterror(req, status);
7368 reply_outbuf(req, 2, 0);
7370 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7371 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7373 END_PROFILE(SMBlockingX);
7378 #define DBGC_CLASS DBGC_ALL
7380 /****************************************************************************
7381 Reply to a SMBreadbmpx (read block multiplex) request.
7382 Always reply with an error, if someone has a platform really needs this,
7383 please contact vl@samba.org
7384 ****************************************************************************/
7386 void reply_readbmpx(struct smb_request *req)
7388 START_PROFILE(SMBreadBmpx);
7389 reply_doserror(req, ERRSRV, ERRuseSTD);
7390 END_PROFILE(SMBreadBmpx);
7394 /****************************************************************************
7395 Reply to a SMBreadbs (read block multiplex secondary) request.
7396 Always reply with an error, if someone has a platform really needs this,
7397 please contact vl@samba.org
7398 ****************************************************************************/
7400 void reply_readbs(struct smb_request *req)
7402 START_PROFILE(SMBreadBs);
7403 reply_doserror(req, ERRSRV, ERRuseSTD);
7404 END_PROFILE(SMBreadBs);
7408 /****************************************************************************
7409 Reply to a SMBsetattrE.
7410 ****************************************************************************/
7412 void reply_setattrE(struct smb_request *req)
7414 connection_struct *conn = req->conn;
7415 struct smb_file_time ft;
7417 SMB_STRUCT_STAT sbuf;
7420 START_PROFILE(SMBsetattrE);
7424 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7425 END_PROFILE(SMBsetattrE);
7429 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7431 if(!fsp || (fsp->conn != conn)) {
7432 reply_doserror(req, ERRDOS, ERRbadfid);
7433 END_PROFILE(SMBsetattrE);
7439 * Convert the DOS times into unix times.
7442 ft.atime = convert_time_t_to_timespec(
7443 srv_make_unix_date2(req->vwv+3));
7444 ft.mtime = convert_time_t_to_timespec(
7445 srv_make_unix_date2(req->vwv+5));
7446 ft.create_time = convert_time_t_to_timespec(
7447 srv_make_unix_date2(req->vwv+1));
7449 reply_outbuf(req, 0, 0);
7452 * Patch from Ray Frush <frush@engr.colostate.edu>
7453 * Sometimes times are sent as zero - ignore them.
7456 /* Ensure we have a valid stat struct for the source. */
7457 if (fsp->fh->fd != -1) {
7458 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7459 status = map_nt_error_from_unix(errno);
7460 reply_nterror(req, status);
7461 END_PROFILE(SMBsetattrE);
7467 if (fsp->posix_open) {
7468 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
7470 ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
7473 status = map_nt_error_from_unix(errno);
7474 reply_nterror(req, status);
7475 END_PROFILE(SMBsetattrE);
7480 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7482 if (!NT_STATUS_IS_OK(status)) {
7483 reply_doserror(req, ERRDOS, ERRnoaccess);
7484 END_PROFILE(SMBsetattrE);
7488 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7491 (unsigned int)ft.atime.tv_sec,
7492 (unsigned int)ft.mtime.tv_sec,
7493 (unsigned int)ft.create_time.tv_sec
7496 END_PROFILE(SMBsetattrE);
7501 /* Back from the dead for OS/2..... JRA. */
7503 /****************************************************************************
7504 Reply to a SMBwritebmpx (write block multiplex primary) request.
7505 Always reply with an error, if someone has a platform really needs this,
7506 please contact vl@samba.org
7507 ****************************************************************************/
7509 void reply_writebmpx(struct smb_request *req)
7511 START_PROFILE(SMBwriteBmpx);
7512 reply_doserror(req, ERRSRV, ERRuseSTD);
7513 END_PROFILE(SMBwriteBmpx);
7517 /****************************************************************************
7518 Reply to a SMBwritebs (write block multiplex secondary) request.
7519 Always reply with an error, if someone has a platform really needs this,
7520 please contact vl@samba.org
7521 ****************************************************************************/
7523 void reply_writebs(struct smb_request *req)
7525 START_PROFILE(SMBwriteBs);
7526 reply_doserror(req, ERRSRV, ERRuseSTD);
7527 END_PROFILE(SMBwriteBs);
7531 /****************************************************************************
7532 Reply to a SMBgetattrE.
7533 ****************************************************************************/
7535 void reply_getattrE(struct smb_request *req)
7537 connection_struct *conn = req->conn;
7538 SMB_STRUCT_STAT sbuf;
7541 struct timespec create_ts;
7543 START_PROFILE(SMBgetattrE);
7546 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7547 END_PROFILE(SMBgetattrE);
7551 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7553 if(!fsp || (fsp->conn != conn)) {
7554 reply_doserror(req, ERRDOS, ERRbadfid);
7555 END_PROFILE(SMBgetattrE);
7559 /* Do an fstat on this file */
7560 if(fsp_stat(fsp, &sbuf)) {
7561 reply_unixerror(req, ERRDOS, ERRnoaccess);
7562 END_PROFILE(SMBgetattrE);
7566 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7569 * Convert the times into dos times. Set create
7570 * date to be last modify date as UNIX doesn't save
7574 reply_outbuf(req, 11, 0);
7576 create_ts = get_create_timespec(&sbuf,
7577 lp_fake_dir_create_times(SNUM(conn)));
7578 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7579 srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7580 /* Should we check pending modtime here ? JRA */
7581 srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7584 SIVAL(req->outbuf, smb_vwv6, 0);
7585 SIVAL(req->outbuf, smb_vwv8, 0);
7587 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7588 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7589 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7591 SSVAL(req->outbuf,smb_vwv10, mode);
7593 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7595 END_PROFILE(SMBgetattrE);