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();
614 struct smbd_server_connection *sconn = smbd_server_conn;
616 START_PROFILE(SMBtcon);
618 if (req->buflen < 4) {
619 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
620 END_PROFILE(SMBtcon);
624 p = (const char *)req->buf + 1;
625 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
627 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
629 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
632 if (service_buf == NULL || password == NULL || dev == NULL) {
633 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
634 END_PROFILE(SMBtcon);
637 p = strrchr_m(service_buf,'\\');
641 service = service_buf;
644 password_blob = data_blob(password, pwlen+1);
646 conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
649 data_blob_clear_free(&password_blob);
652 reply_nterror(req, nt_status);
653 END_PROFILE(SMBtcon);
657 reply_outbuf(req, 2, 0);
658 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
659 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
660 SSVAL(req->outbuf,smb_tid,conn->cnum);
662 DEBUG(3,("tcon service=%s cnum=%d\n",
663 service, conn->cnum));
665 END_PROFILE(SMBtcon);
669 /****************************************************************************
670 Reply to a tcon and X.
671 conn POINTER CAN BE NULL HERE !
672 ****************************************************************************/
674 void reply_tcon_and_X(struct smb_request *req)
676 connection_struct *conn = req->conn;
677 const char *service = NULL;
679 TALLOC_CTX *ctx = talloc_tos();
680 /* what the cleint thinks the device is */
681 char *client_devicetype = NULL;
682 /* what the server tells the client the share represents */
683 const char *server_devicetype;
689 struct smbd_server_connection *sconn = smbd_server_conn;
691 START_PROFILE(SMBtconX);
694 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
695 END_PROFILE(SMBtconX);
699 passlen = SVAL(req->vwv+3, 0);
700 tcon_flags = SVAL(req->vwv+2, 0);
702 /* we might have to close an old one */
703 if ((tcon_flags & 0x1) && conn) {
704 close_cnum(conn,req->vuid);
709 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
710 reply_doserror(req, ERRDOS, ERRbuftoosmall);
711 END_PROFILE(SMBtconX);
715 if (sconn->smb1.negprot.encrypted_passwords) {
716 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
717 if (lp_security() == SEC_SHARE) {
719 * Security = share always has a pad byte
720 * after the password.
722 p = (const char *)req->buf + passlen + 1;
724 p = (const char *)req->buf + passlen;
727 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
728 /* Ensure correct termination */
729 password.data[passlen]=0;
730 p = (const char *)req->buf + passlen + 1;
733 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
736 data_blob_clear_free(&password);
737 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
738 END_PROFILE(SMBtconX);
743 * the service name can be either: \\server\share
744 * or share directly like on the DELL PowerVault 705
747 q = strchr_m(path+2,'\\');
749 data_blob_clear_free(&password);
750 reply_doserror(req, ERRDOS, ERRnosuchshare);
751 END_PROFILE(SMBtconX);
759 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
760 &client_devicetype, p,
761 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
763 if (client_devicetype == NULL) {
764 data_blob_clear_free(&password);
765 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
766 END_PROFILE(SMBtconX);
770 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
772 conn = make_connection(service, password, client_devicetype,
773 req->vuid, &nt_status);
776 data_blob_clear_free(&password);
779 reply_nterror(req, nt_status);
780 END_PROFILE(SMBtconX);
785 server_devicetype = "IPC";
786 else if ( IS_PRINT(conn) )
787 server_devicetype = "LPT1:";
789 server_devicetype = "A:";
791 if (Protocol < PROTOCOL_NT1) {
792 reply_outbuf(req, 2, 0);
793 if (message_push_string(&req->outbuf, server_devicetype,
794 STR_TERMINATE|STR_ASCII) == -1) {
795 reply_nterror(req, NT_STATUS_NO_MEMORY);
796 END_PROFILE(SMBtconX);
800 /* NT sets the fstype of IPC$ to the null string */
801 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
803 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
804 /* Return permissions. */
808 reply_outbuf(req, 7, 0);
811 perm1 = FILE_ALL_ACCESS;
812 perm2 = FILE_ALL_ACCESS;
814 perm1 = CAN_WRITE(conn) ?
819 SIVAL(req->outbuf, smb_vwv3, perm1);
820 SIVAL(req->outbuf, smb_vwv5, perm2);
822 reply_outbuf(req, 3, 0);
825 if ((message_push_string(&req->outbuf, server_devicetype,
826 STR_TERMINATE|STR_ASCII) == -1)
827 || (message_push_string(&req->outbuf, fstype,
828 STR_TERMINATE) == -1)) {
829 reply_nterror(req, NT_STATUS_NO_MEMORY);
830 END_PROFILE(SMBtconX);
834 /* what does setting this bit do? It is set by NT4 and
835 may affect the ability to autorun mounted cdroms */
836 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
837 (lp_csc_policy(SNUM(conn)) << 2));
839 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
840 DEBUG(2,("Serving %s as a Dfs root\n",
841 lp_servicename(SNUM(conn)) ));
842 SSVAL(req->outbuf, smb_vwv2,
843 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
848 DEBUG(3,("tconX service=%s \n",
851 /* set the incoming and outgoing tid to the just created one */
852 SSVAL(req->inbuf,smb_tid,conn->cnum);
853 SSVAL(req->outbuf,smb_tid,conn->cnum);
855 END_PROFILE(SMBtconX);
861 /****************************************************************************
862 Reply to an unknown type.
863 ****************************************************************************/
865 void reply_unknown_new(struct smb_request *req, uint8 type)
867 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
868 smb_fn_name(type), type, type));
869 reply_doserror(req, ERRSRV, ERRunknownsmb);
873 /****************************************************************************
875 conn POINTER CAN BE NULL HERE !
876 ****************************************************************************/
878 void reply_ioctl(struct smb_request *req)
880 connection_struct *conn = req->conn;
887 START_PROFILE(SMBioctl);
890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
891 END_PROFILE(SMBioctl);
895 device = SVAL(req->vwv+1, 0);
896 function = SVAL(req->vwv+2, 0);
897 ioctl_code = (device << 16) + function;
899 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
901 switch (ioctl_code) {
902 case IOCTL_QUERY_JOB_INFO:
906 reply_doserror(req, ERRSRV, ERRnosupport);
907 END_PROFILE(SMBioctl);
911 reply_outbuf(req, 8, replysize+1);
912 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
913 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
914 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
915 p = smb_buf(req->outbuf);
916 memset(p, '\0', replysize+1); /* valgrind-safe. */
917 p += 1; /* Allow for alignment */
919 switch (ioctl_code) {
920 case IOCTL_QUERY_JOB_INFO:
922 files_struct *fsp = file_fsp(
923 req, SVAL(req->vwv+0, 0));
925 reply_doserror(req, ERRDOS, ERRbadfid);
926 END_PROFILE(SMBioctl);
929 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
930 srvstr_push((char *)req->outbuf, req->flags2, p+2,
932 STR_TERMINATE|STR_ASCII);
934 srvstr_push((char *)req->outbuf, req->flags2,
935 p+18, lp_servicename(SNUM(conn)),
936 13, STR_TERMINATE|STR_ASCII);
944 END_PROFILE(SMBioctl);
948 /****************************************************************************
949 Strange checkpath NTSTATUS mapping.
950 ****************************************************************************/
952 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
954 /* Strange DOS error code semantics only for checkpath... */
955 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
956 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
957 /* We need to map to ERRbadpath */
958 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
964 /****************************************************************************
965 Reply to a checkpath.
966 ****************************************************************************/
968 void reply_checkpath(struct smb_request *req)
970 connection_struct *conn = req->conn;
971 struct smb_filename *smb_fname = NULL;
974 TALLOC_CTX *ctx = talloc_tos();
976 START_PROFILE(SMBcheckpath);
978 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
979 STR_TERMINATE, &status);
981 if (!NT_STATUS_IS_OK(status)) {
982 status = map_checkpath_error(req->flags2, status);
983 reply_nterror(req, status);
984 END_PROFILE(SMBcheckpath);
988 status = resolve_dfspath(ctx, conn,
989 req->flags2 & FLAGS2_DFS_PATHNAMES,
992 if (!NT_STATUS_IS_OK(status)) {
993 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
994 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
996 END_PROFILE(SMBcheckpath);
1002 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1004 status = unix_convert(ctx, conn, name, &smb_fname, 0);
1005 if (!NT_STATUS_IS_OK(status)) {
1009 status = get_full_smb_filename(ctx, smb_fname, &name);
1010 if (!NT_STATUS_IS_OK(status)) {
1014 status = check_name(conn, name);
1015 if (!NT_STATUS_IS_OK(status)) {
1016 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
1020 if (!VALID_STAT(smb_fname->st) &&
1021 (SMB_VFS_STAT(conn, name, &smb_fname->st) != 0)) {
1022 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
1023 status = map_nt_error_from_unix(errno);
1027 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1028 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1029 ERRDOS, ERRbadpath);
1033 reply_outbuf(req, 0, 0);
1035 TALLOC_FREE(smb_fname);
1036 END_PROFILE(SMBcheckpath);
1041 TALLOC_FREE(smb_fname);
1043 END_PROFILE(SMBcheckpath);
1045 /* We special case this - as when a Windows machine
1046 is parsing a path is steps through the components
1047 one at a time - if a component fails it expects
1048 ERRbadpath, not ERRbadfile.
1050 status = map_checkpath_error(req->flags2, status);
1051 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1053 * Windows returns different error codes if
1054 * the parent directory is valid but not the
1055 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1056 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1057 * if the path is invalid.
1059 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1060 ERRDOS, ERRbadpath);
1064 reply_nterror(req, status);
1067 /****************************************************************************
1069 ****************************************************************************/
1071 void reply_getatr(struct smb_request *req)
1073 connection_struct *conn = req->conn;
1074 struct smb_filename *smb_fname = NULL;
1081 TALLOC_CTX *ctx = talloc_tos();
1083 START_PROFILE(SMBgetatr);
1085 p = (const char *)req->buf + 1;
1086 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1087 if (!NT_STATUS_IS_OK(status)) {
1088 reply_nterror(req, status);
1092 status = resolve_dfspath(ctx, conn,
1093 req->flags2 & FLAGS2_DFS_PATHNAMES,
1096 if (!NT_STATUS_IS_OK(status)) {
1097 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1098 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1099 ERRSRV, ERRbadpath);
1102 reply_nterror(req, status);
1106 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1107 under WfWg - weird! */
1108 if (*fname == '\0') {
1109 mode = aHIDDEN | aDIR;
1110 if (!CAN_WRITE(conn)) {
1116 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1117 if (!NT_STATUS_IS_OK(status)) {
1118 reply_nterror(req, status);
1121 status = get_full_smb_filename(ctx, smb_fname, &fname);
1122 if (!NT_STATUS_IS_OK(status)) {
1123 reply_nterror(req, status);
1126 status = check_name(conn, fname);
1127 if (!NT_STATUS_IS_OK(status)) {
1128 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1129 reply_nterror(req, status);
1132 if (!VALID_STAT(smb_fname->st) &&
1133 (SMB_VFS_STAT(conn, fname, &smb_fname->st) != 0)) {
1134 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1135 reply_unixerror(req, ERRDOS,ERRbadfile);
1139 mode = dos_mode(conn, fname, &smb_fname->st);
1140 size = smb_fname->st.st_ex_size;
1141 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1147 reply_outbuf(req, 10, 0);
1149 SSVAL(req->outbuf,smb_vwv0,mode);
1150 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1151 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1153 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1155 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1157 if (Protocol >= PROTOCOL_NT1) {
1158 SSVAL(req->outbuf, smb_flg2,
1159 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1162 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1165 TALLOC_FREE(smb_fname);
1166 END_PROFILE(SMBgetatr);
1170 /****************************************************************************
1172 ****************************************************************************/
1174 void reply_setatr(struct smb_request *req)
1176 struct smb_file_time ft;
1177 connection_struct *conn = req->conn;
1178 struct smb_filename *smb_fname = NULL;
1184 TALLOC_CTX *ctx = talloc_tos();
1186 START_PROFILE(SMBsetatr);
1191 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1195 p = (const char *)req->buf + 1;
1196 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1197 if (!NT_STATUS_IS_OK(status)) {
1198 reply_nterror(req, status);
1202 status = resolve_dfspath(ctx, conn,
1203 req->flags2 & FLAGS2_DFS_PATHNAMES,
1206 if (!NT_STATUS_IS_OK(status)) {
1207 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1208 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1209 ERRSRV, ERRbadpath);
1212 reply_nterror(req, status);
1216 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1217 if (!NT_STATUS_IS_OK(status)) {
1218 reply_nterror(req, status);
1222 status = get_full_smb_filename(ctx, smb_fname, &fname);
1223 if (!NT_STATUS_IS_OK(status)) {
1224 reply_nterror(req, status);
1228 status = check_name(conn, fname);
1229 if (!NT_STATUS_IS_OK(status)) {
1230 reply_nterror(req, status);
1234 if (fname[0] == '.' && fname[1] == '\0') {
1236 * Not sure here is the right place to catch this
1237 * condition. Might be moved to somewhere else later -- vl
1239 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1243 mode = SVAL(req->vwv+0, 0);
1244 mtime = srv_make_unix_date3(req->vwv+1);
1246 ft.mtime = convert_time_t_to_timespec(mtime);
1247 status = smb_set_file_time(conn, NULL, fname,
1248 &smb_fname->st, &ft, true);
1249 if (!NT_STATUS_IS_OK(status)) {
1250 reply_unixerror(req, ERRDOS, ERRnoaccess);
1254 if (mode != FILE_ATTRIBUTE_NORMAL) {
1255 if (VALID_STAT_OF_DIR(smb_fname->st))
1260 if (file_set_dosmode(conn, fname, mode, &smb_fname->st, NULL,
1262 reply_unixerror(req, ERRDOS, ERRnoaccess);
1267 reply_outbuf(req, 0, 0);
1269 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1271 TALLOC_FREE(smb_fname);
1272 END_PROFILE(SMBsetatr);
1276 /****************************************************************************
1278 ****************************************************************************/
1280 void reply_dskattr(struct smb_request *req)
1282 connection_struct *conn = req->conn;
1283 uint64_t dfree,dsize,bsize;
1284 START_PROFILE(SMBdskattr);
1286 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1287 reply_unixerror(req, ERRHRD, ERRgeneral);
1288 END_PROFILE(SMBdskattr);
1292 reply_outbuf(req, 5, 0);
1294 if (Protocol <= PROTOCOL_LANMAN2) {
1295 double total_space, free_space;
1296 /* we need to scale this to a number that DOS6 can handle. We
1297 use floating point so we can handle large drives on systems
1298 that don't have 64 bit integers
1300 we end up displaying a maximum of 2G to DOS systems
1302 total_space = dsize * (double)bsize;
1303 free_space = dfree * (double)bsize;
1305 dsize = (uint64_t)((total_space+63*512) / (64*512));
1306 dfree = (uint64_t)((free_space+63*512) / (64*512));
1308 if (dsize > 0xFFFF) dsize = 0xFFFF;
1309 if (dfree > 0xFFFF) dfree = 0xFFFF;
1311 SSVAL(req->outbuf,smb_vwv0,dsize);
1312 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1313 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1314 SSVAL(req->outbuf,smb_vwv3,dfree);
1316 SSVAL(req->outbuf,smb_vwv0,dsize);
1317 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1318 SSVAL(req->outbuf,smb_vwv2,512);
1319 SSVAL(req->outbuf,smb_vwv3,dfree);
1322 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1324 END_PROFILE(SMBdskattr);
1328 /****************************************************************************
1330 Can be called from SMBsearch, SMBffirst or SMBfunique.
1331 ****************************************************************************/
1333 void reply_search(struct smb_request *req)
1335 connection_struct *conn = req->conn;
1336 const char *mask = NULL;
1337 char *directory = NULL;
1341 struct timespec date;
1343 unsigned int numentries = 0;
1344 unsigned int maxentries = 0;
1345 bool finished = False;
1351 bool check_descend = False;
1352 bool expect_close = False;
1354 bool mask_contains_wcard = False;
1355 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1356 TALLOC_CTX *ctx = talloc_tos();
1357 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1359 START_PROFILE(SMBsearch);
1362 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1363 END_PROFILE(SMBsearch);
1367 if (lp_posix_pathnames()) {
1368 reply_unknown_new(req, req->cmd);
1369 END_PROFILE(SMBsearch);
1373 /* If we were called as SMBffirst then we must expect close. */
1374 if(req->cmd == SMBffirst) {
1375 expect_close = True;
1378 reply_outbuf(req, 1, 3);
1379 maxentries = SVAL(req->vwv+0, 0);
1380 dirtype = SVAL(req->vwv+1, 0);
1381 p = (const char *)req->buf + 1;
1382 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1383 &nt_status, &mask_contains_wcard);
1384 if (!NT_STATUS_IS_OK(nt_status)) {
1385 reply_nterror(req, nt_status);
1386 END_PROFILE(SMBsearch);
1390 nt_status = resolve_dfspath_wcard(ctx, conn,
1391 req->flags2 & FLAGS2_DFS_PATHNAMES,
1394 &mask_contains_wcard);
1395 if (!NT_STATUS_IS_OK(nt_status)) {
1396 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1397 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1398 ERRSRV, ERRbadpath);
1399 END_PROFILE(SMBsearch);
1402 reply_nterror(req, nt_status);
1403 END_PROFILE(SMBsearch);
1408 status_len = SVAL(p, 0);
1411 /* dirtype &= ~aDIR; */
1413 if (status_len == 0) {
1414 struct smb_filename *smb_fname = NULL;
1416 nt_status = unix_convert(ctx, conn, path, &smb_fname,
1417 UCF_ALLOW_WCARD_LCOMP);
1418 if (!NT_STATUS_IS_OK(nt_status)) {
1419 reply_nterror(req, nt_status);
1420 END_PROFILE(SMBsearch);
1424 nt_status = get_full_smb_filename(ctx, smb_fname, &directory);
1425 TALLOC_FREE(smb_fname);
1426 if (!NT_STATUS_IS_OK(nt_status)) {
1427 reply_nterror(req, nt_status);
1428 END_PROFILE(SMBsearch);
1432 nt_status = check_name(conn, directory);
1433 if (!NT_STATUS_IS_OK(nt_status)) {
1434 reply_nterror(req, nt_status);
1435 END_PROFILE(SMBsearch);
1439 p = strrchr_m(directory,'/');
1440 if ((p != NULL) && (*directory != '/')) {
1442 directory = talloc_strndup(ctx, directory,
1443 PTR_DIFF(p, directory));
1446 directory = talloc_strdup(ctx,".");
1450 reply_nterror(req, NT_STATUS_NO_MEMORY);
1451 END_PROFILE(SMBsearch);
1455 memset((char *)status,'\0',21);
1456 SCVAL(status,0,(dirtype & 0x1F));
1458 nt_status = dptr_create(conn,
1464 mask_contains_wcard,
1467 if (!NT_STATUS_IS_OK(nt_status)) {
1468 reply_nterror(req, nt_status);
1469 END_PROFILE(SMBsearch);
1472 dptr_num = dptr_dnum(conn->dirptr);
1476 memcpy(status,p,21);
1477 status_dirtype = CVAL(status,0) & 0x1F;
1478 if (status_dirtype != (dirtype & 0x1F)) {
1479 dirtype = status_dirtype;
1482 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1483 if (!conn->dirptr) {
1486 string_set(&conn->dirpath,dptr_path(dptr_num));
1487 mask = dptr_wcard(dptr_num);
1492 * For a 'continue' search we have no string. So
1493 * check from the initial saved string.
1495 mask_contains_wcard = ms_has_wild(mask);
1496 dirtype = dptr_attr(dptr_num);
1499 DEBUG(4,("dptr_num is %d\n",dptr_num));
1501 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1502 dptr_init_search_op(conn->dirptr);
1504 if ((dirtype&0x1F) == aVOLID) {
1505 char buf[DIR_STRUCT_SIZE];
1506 memcpy(buf,status,21);
1507 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1508 0,aVOLID,0,!allow_long_path_components)) {
1509 reply_nterror(req, NT_STATUS_NO_MEMORY);
1510 END_PROFILE(SMBsearch);
1513 dptr_fill(buf+12,dptr_num);
1514 if (dptr_zero(buf+12) && (status_len==0)) {
1519 if (message_push_blob(&req->outbuf,
1520 data_blob_const(buf, sizeof(buf)))
1522 reply_nterror(req, NT_STATUS_NO_MEMORY);
1523 END_PROFILE(SMBsearch);
1531 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1534 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1535 conn->dirpath,lp_dontdescend(SNUM(conn))));
1536 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1537 check_descend = True;
1540 for (i=numentries;(i<maxentries) && !finished;i++) {
1541 finished = !get_dir_entry(ctx,
1552 char buf[DIR_STRUCT_SIZE];
1553 memcpy(buf,status,21);
1554 if (!make_dir_struct(ctx,
1560 convert_timespec_to_time_t(date),
1561 !allow_long_path_components)) {
1562 reply_nterror(req, NT_STATUS_NO_MEMORY);
1563 END_PROFILE(SMBsearch);
1566 if (!dptr_fill(buf+12,dptr_num)) {
1569 if (message_push_blob(&req->outbuf,
1570 data_blob_const(buf, sizeof(buf)))
1572 reply_nterror(req, NT_STATUS_NO_MEMORY);
1573 END_PROFILE(SMBsearch);
1583 /* If we were called as SMBffirst with smb_search_id == NULL
1584 and no entries were found then return error and close dirptr
1587 if (numentries == 0) {
1588 dptr_close(&dptr_num);
1589 } else if(expect_close && status_len == 0) {
1590 /* Close the dptr - we know it's gone */
1591 dptr_close(&dptr_num);
1594 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1595 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1596 dptr_close(&dptr_num);
1599 if ((numentries == 0) && !mask_contains_wcard) {
1600 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1601 END_PROFILE(SMBsearch);
1605 SSVAL(req->outbuf,smb_vwv0,numentries);
1606 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1607 SCVAL(smb_buf(req->outbuf),0,5);
1608 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1610 /* The replies here are never long name. */
1611 SSVAL(req->outbuf, smb_flg2,
1612 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1613 if (!allow_long_path_components) {
1614 SSVAL(req->outbuf, smb_flg2,
1615 SVAL(req->outbuf, smb_flg2)
1616 & (~FLAGS2_LONG_PATH_COMPONENTS));
1619 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1620 SSVAL(req->outbuf, smb_flg2,
1621 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1624 directory = dptr_path(dptr_num);
1627 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1628 smb_fn_name(req->cmd),
1630 directory ? directory : "./",
1635 END_PROFILE(SMBsearch);
1639 /****************************************************************************
1640 Reply to a fclose (stop directory search).
1641 ****************************************************************************/
1643 void reply_fclose(struct smb_request *req)
1651 bool path_contains_wcard = False;
1652 TALLOC_CTX *ctx = talloc_tos();
1654 START_PROFILE(SMBfclose);
1656 if (lp_posix_pathnames()) {
1657 reply_unknown_new(req, req->cmd);
1658 END_PROFILE(SMBfclose);
1662 p = (const char *)req->buf + 1;
1663 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1664 &err, &path_contains_wcard);
1665 if (!NT_STATUS_IS_OK(err)) {
1666 reply_nterror(req, err);
1667 END_PROFILE(SMBfclose);
1671 status_len = SVAL(p,0);
1674 if (status_len == 0) {
1675 reply_doserror(req, ERRSRV, ERRsrverror);
1676 END_PROFILE(SMBfclose);
1680 memcpy(status,p,21);
1682 if(dptr_fetch(status+12,&dptr_num)) {
1683 /* Close the dptr - we know it's gone */
1684 dptr_close(&dptr_num);
1687 reply_outbuf(req, 1, 0);
1688 SSVAL(req->outbuf,smb_vwv0,0);
1690 DEBUG(3,("search close\n"));
1692 END_PROFILE(SMBfclose);
1696 /****************************************************************************
1698 ****************************************************************************/
1700 void reply_open(struct smb_request *req)
1702 connection_struct *conn = req->conn;
1708 SMB_STRUCT_STAT sbuf;
1715 uint32 create_disposition;
1716 uint32 create_options = 0;
1718 TALLOC_CTX *ctx = talloc_tos();
1720 START_PROFILE(SMBopen);
1722 SET_STAT_INVALID(sbuf);
1725 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1726 END_PROFILE(SMBopen);
1730 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1731 deny_mode = SVAL(req->vwv+0, 0);
1732 dos_attr = SVAL(req->vwv+1, 0);
1734 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1735 STR_TERMINATE, &status);
1736 if (!NT_STATUS_IS_OK(status)) {
1737 reply_nterror(req, status);
1738 END_PROFILE(SMBopen);
1742 if (!map_open_params_to_ntcreate(
1743 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1744 &share_mode, &create_disposition, &create_options)) {
1745 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1746 END_PROFILE(SMBopen);
1750 status = SMB_VFS_CREATE_FILE(
1753 0, /* root_dir_fid */
1755 CFF_DOS_PATH, /* create_file_flags */
1756 access_mask, /* access_mask */
1757 share_mode, /* share_access */
1758 create_disposition, /* create_disposition*/
1759 create_options, /* create_options */
1760 dos_attr, /* file_attributes */
1761 oplock_request, /* oplock_request */
1762 0, /* allocation_size */
1769 if (!NT_STATUS_IS_OK(status)) {
1770 if (open_was_deferred(req->mid)) {
1771 /* We have re-scheduled this call. */
1772 END_PROFILE(SMBopen);
1775 reply_openerror(req, status);
1776 END_PROFILE(SMBopen);
1780 size = sbuf.st_ex_size;
1781 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1782 mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime);
1785 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1786 close_file(req, fsp, ERROR_CLOSE);
1787 reply_doserror(req, ERRDOS,ERRnoaccess);
1788 END_PROFILE(SMBopen);
1792 reply_outbuf(req, 7, 0);
1793 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1794 SSVAL(req->outbuf,smb_vwv1,fattr);
1795 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1796 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1798 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1800 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1801 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1803 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1804 SCVAL(req->outbuf,smb_flg,
1805 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1808 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1809 SCVAL(req->outbuf,smb_flg,
1810 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1812 END_PROFILE(SMBopen);
1816 /****************************************************************************
1817 Reply to an open and X.
1818 ****************************************************************************/
1820 void reply_open_and_X(struct smb_request *req)
1822 connection_struct *conn = req->conn;
1827 /* Breakout the oplock request bits so we can set the
1828 reply bits separately. */
1829 int ex_oplock_request;
1830 int core_oplock_request;
1833 int smb_sattr = SVAL(req->vwv+4, 0);
1834 uint32 smb_time = make_unix_date3(req->vwv+6);
1839 SMB_STRUCT_STAT sbuf;
1843 uint64_t allocation_size;
1844 ssize_t retval = -1;
1847 uint32 create_disposition;
1848 uint32 create_options = 0;
1849 TALLOC_CTX *ctx = talloc_tos();
1851 START_PROFILE(SMBopenX);
1853 if (req->wct < 15) {
1854 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1855 END_PROFILE(SMBopenX);
1859 SET_STAT_INVALID(sbuf);
1861 open_flags = SVAL(req->vwv+2, 0);
1862 deny_mode = SVAL(req->vwv+3, 0);
1863 smb_attr = SVAL(req->vwv+5, 0);
1864 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1865 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1866 oplock_request = ex_oplock_request | core_oplock_request;
1867 smb_ofun = SVAL(req->vwv+8, 0);
1868 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1870 /* If it's an IPC, pass off the pipe handler. */
1872 if (lp_nt_pipe_support()) {
1873 reply_open_pipe_and_X(conn, req);
1875 reply_doserror(req, ERRSRV, ERRaccess);
1877 END_PROFILE(SMBopenX);
1881 /* XXXX we need to handle passed times, sattr and flags */
1882 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1883 STR_TERMINATE, &status);
1884 if (!NT_STATUS_IS_OK(status)) {
1885 reply_nterror(req, status);
1886 END_PROFILE(SMBopenX);
1890 if (!map_open_params_to_ntcreate(
1891 fname, deny_mode, smb_ofun, &access_mask,
1892 &share_mode, &create_disposition, &create_options)) {
1893 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1894 END_PROFILE(SMBopenX);
1898 status = SMB_VFS_CREATE_FILE(
1901 0, /* root_dir_fid */
1903 CFF_DOS_PATH, /* create_file_flags */
1904 access_mask, /* access_mask */
1905 share_mode, /* share_access */
1906 create_disposition, /* create_disposition*/
1907 create_options, /* create_options */
1908 smb_attr, /* file_attributes */
1909 oplock_request, /* oplock_request */
1910 0, /* allocation_size */
1914 &smb_action, /* pinfo */
1917 if (!NT_STATUS_IS_OK(status)) {
1918 END_PROFILE(SMBopenX);
1919 if (open_was_deferred(req->mid)) {
1920 /* We have re-scheduled this call. */
1923 reply_openerror(req, status);
1927 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1928 if the file is truncated or created. */
1929 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1930 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1931 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1932 close_file(req, fsp, ERROR_CLOSE);
1933 reply_nterror(req, NT_STATUS_DISK_FULL);
1934 END_PROFILE(SMBopenX);
1937 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1939 close_file(req, fsp, ERROR_CLOSE);
1940 reply_nterror(req, NT_STATUS_DISK_FULL);
1941 END_PROFILE(SMBopenX);
1944 sbuf.st_ex_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
1947 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1948 mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime);
1950 close_file(req, fsp, ERROR_CLOSE);
1951 reply_doserror(req, ERRDOS, ERRnoaccess);
1952 END_PROFILE(SMBopenX);
1956 /* If the caller set the extended oplock request bit
1957 and we granted one (by whatever means) - set the
1958 correct bit for extended oplock reply.
1961 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1962 smb_action |= EXTENDED_OPLOCK_GRANTED;
1965 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1966 smb_action |= EXTENDED_OPLOCK_GRANTED;
1969 /* If the caller set the core oplock request bit
1970 and we granted one (by whatever means) - set the
1971 correct bit for core oplock reply.
1974 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1975 reply_outbuf(req, 19, 0);
1977 reply_outbuf(req, 15, 0);
1980 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1981 SCVAL(req->outbuf, smb_flg,
1982 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1985 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1986 SCVAL(req->outbuf, smb_flg,
1987 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1990 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1991 SSVAL(req->outbuf,smb_vwv3,fattr);
1992 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1993 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1995 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1997 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_ex_size);
1998 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1999 SSVAL(req->outbuf,smb_vwv11,smb_action);
2001 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2002 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2005 END_PROFILE(SMBopenX);
2010 /****************************************************************************
2011 Reply to a SMBulogoffX.
2012 ****************************************************************************/
2014 void reply_ulogoffX(struct smb_request *req)
2018 START_PROFILE(SMBulogoffX);
2020 vuser = get_valid_user_struct(req->vuid);
2023 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2027 /* in user level security we are supposed to close any files
2028 open by this user */
2029 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2030 file_close_user(req->vuid);
2033 invalidate_vuid(req->vuid);
2035 reply_outbuf(req, 2, 0);
2037 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2039 END_PROFILE(SMBulogoffX);
2043 /****************************************************************************
2044 Reply to a mknew or a create.
2045 ****************************************************************************/
2047 void reply_mknew(struct smb_request *req)
2049 connection_struct *conn = req->conn;
2052 struct smb_file_time ft;
2054 int oplock_request = 0;
2055 SMB_STRUCT_STAT sbuf;
2057 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2058 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2059 uint32 create_disposition;
2060 uint32 create_options = 0;
2061 TALLOC_CTX *ctx = talloc_tos();
2063 START_PROFILE(SMBcreate);
2065 SET_STAT_INVALID(sbuf);
2068 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2069 END_PROFILE(SMBcreate);
2073 fattr = SVAL(req->vwv+0, 0);
2074 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2077 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2079 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2080 STR_TERMINATE, &status);
2081 if (!NT_STATUS_IS_OK(status)) {
2082 reply_nterror(req, status);
2083 END_PROFILE(SMBcreate);
2087 if (fattr & aVOLID) {
2088 DEBUG(0,("Attempt to create file (%s) with volid set - "
2089 "please report this\n", fname));
2092 if(req->cmd == SMBmknew) {
2093 /* We should fail if file exists. */
2094 create_disposition = FILE_CREATE;
2096 /* Create if file doesn't exist, truncate if it does. */
2097 create_disposition = FILE_OVERWRITE_IF;
2100 status = SMB_VFS_CREATE_FILE(
2103 0, /* root_dir_fid */
2105 CFF_DOS_PATH, /* create_file_flags */
2106 access_mask, /* access_mask */
2107 share_mode, /* share_access */
2108 create_disposition, /* create_disposition*/
2109 create_options, /* create_options */
2110 fattr, /* file_attributes */
2111 oplock_request, /* oplock_request */
2112 0, /* allocation_size */
2119 if (!NT_STATUS_IS_OK(status)) {
2120 END_PROFILE(SMBcreate);
2121 if (open_was_deferred(req->mid)) {
2122 /* We have re-scheduled this call. */
2125 reply_openerror(req, status);
2129 ft.atime = sbuf.st_ex_atime; /* atime. */
2130 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true);
2131 if (!NT_STATUS_IS_OK(status)) {
2132 END_PROFILE(SMBcreate);
2133 reply_openerror(req, status);
2137 reply_outbuf(req, 1, 0);
2138 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2140 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2141 SCVAL(req->outbuf,smb_flg,
2142 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2145 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2146 SCVAL(req->outbuf,smb_flg,
2147 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2150 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2151 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2152 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2154 END_PROFILE(SMBcreate);
2158 /****************************************************************************
2159 Reply to a create temporary file.
2160 ****************************************************************************/
2162 void reply_ctemp(struct smb_request *req)
2164 connection_struct *conn = req->conn;
2165 struct smb_filename *smb_fname = NULL;
2173 TALLOC_CTX *ctx = talloc_tos();
2175 START_PROFILE(SMBctemp);
2178 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2182 fattr = SVAL(req->vwv+0, 0);
2183 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2185 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2186 STR_TERMINATE, &status);
2187 if (!NT_STATUS_IS_OK(status)) {
2188 reply_nterror(req, status);
2192 fname = talloc_asprintf(ctx,
2196 fname = talloc_strdup(ctx, "TMXXXXXX");
2200 reply_nterror(req, NT_STATUS_NO_MEMORY);
2204 status = resolve_dfspath(ctx, conn,
2205 req->flags2 & FLAGS2_DFS_PATHNAMES,
2208 if (!NT_STATUS_IS_OK(status)) {
2209 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2210 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2211 ERRSRV, ERRbadpath);
2214 reply_nterror(req, status);
2218 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
2219 if (!NT_STATUS_IS_OK(status)) {
2220 reply_nterror(req, status);
2224 status = get_full_smb_filename(ctx, smb_fname, &fname);
2225 if (!NT_STATUS_IS_OK(status)) {
2226 reply_nterror(req, status);
2230 status = check_name(conn, fname);
2231 if (!NT_STATUS_IS_OK(status)) {
2232 reply_nterror(req, status);
2236 tmpfd = mkstemp(fname);
2238 reply_unixerror(req, ERRDOS, ERRnoaccess);
2242 SET_STAT_INVALID(smb_fname->st);
2243 SMB_VFS_STAT(conn, fname, &smb_fname->st);
2245 /* We should fail if file does not exist. */
2246 status = SMB_VFS_CREATE_FILE(
2249 0, /* root_dir_fid */
2251 0, /* create_file_flags */
2252 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2253 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2254 FILE_OPEN, /* create_disposition*/
2255 0, /* create_options */
2256 fattr, /* file_attributes */
2257 oplock_request, /* oplock_request */
2258 0, /* allocation_size */
2263 &smb_fname->st); /* psbuf */
2265 /* close fd from mkstemp() */
2268 if (!NT_STATUS_IS_OK(status)) {
2269 if (open_was_deferred(req->mid)) {
2270 /* We have re-scheduled this call. */
2273 reply_openerror(req, status);
2277 reply_outbuf(req, 1, 0);
2278 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2280 /* the returned filename is relative to the directory */
2281 s = strrchr_m(fsp->fsp_name, '/');
2289 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2290 thing in the byte section. JRA */
2291 SSVALS(p, 0, -1); /* what is this? not in spec */
2293 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2295 reply_nterror(req, NT_STATUS_NO_MEMORY);
2299 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2300 SCVAL(req->outbuf, smb_flg,
2301 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2304 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2305 SCVAL(req->outbuf, smb_flg,
2306 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2309 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2310 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2311 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2313 TALLOC_FREE(smb_fname);
2314 END_PROFILE(SMBctemp);
2318 /*******************************************************************
2319 Check if a user is allowed to rename a file.
2320 ********************************************************************/
2322 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2323 uint16 dirtype, SMB_STRUCT_STAT *pst)
2327 if (!CAN_WRITE(conn)) {
2328 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2331 fmode = dos_mode(conn, fsp->fsp_name, pst);
2332 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2333 return NT_STATUS_NO_SUCH_FILE;
2336 if (S_ISDIR(pst->st_ex_mode)) {
2337 if (fsp->posix_open) {
2338 return NT_STATUS_OK;
2341 /* If no pathnames are open below this
2342 directory, allow the rename. */
2344 if (file_find_subpath(fsp)) {
2345 return NT_STATUS_ACCESS_DENIED;
2347 return NT_STATUS_OK;
2350 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2351 return NT_STATUS_OK;
2354 return NT_STATUS_ACCESS_DENIED;
2357 /*******************************************************************
2358 * unlink a file with all relevant access checks
2359 *******************************************************************/
2361 static NTSTATUS do_unlink(connection_struct *conn,
2362 struct smb_request *req,
2366 SMB_STRUCT_STAT sbuf;
2369 uint32 dirtype_orig = dirtype;
2372 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2374 if (!CAN_WRITE(conn)) {
2375 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2378 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2379 return map_nt_error_from_unix(errno);
2382 fattr = dos_mode(conn,fname,&sbuf);
2384 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2385 dirtype = aDIR|aARCH|aRONLY;
2388 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2390 return NT_STATUS_NO_SUCH_FILE;
2393 if (!dir_check_ftype(conn, fattr, dirtype)) {
2395 return NT_STATUS_FILE_IS_A_DIRECTORY;
2397 return NT_STATUS_NO_SUCH_FILE;
2400 if (dirtype_orig & 0x8000) {
2401 /* These will never be set for POSIX. */
2402 return NT_STATUS_NO_SUCH_FILE;
2406 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2407 return NT_STATUS_FILE_IS_A_DIRECTORY;
2410 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2411 return NT_STATUS_NO_SUCH_FILE;
2414 if (dirtype & 0xFF00) {
2415 /* These will never be set for POSIX. */
2416 return NT_STATUS_NO_SUCH_FILE;
2421 return NT_STATUS_NO_SUCH_FILE;
2424 /* Can't delete a directory. */
2426 return NT_STATUS_FILE_IS_A_DIRECTORY;
2431 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2432 return NT_STATUS_OBJECT_NAME_INVALID;
2433 #endif /* JRATEST */
2435 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2437 On a Windows share, a file with read-only dosmode can be opened with
2438 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2439 fails with NT_STATUS_CANNOT_DELETE error.
2441 This semantic causes a problem that a user can not
2442 rename a file with read-only dosmode on a Samba share
2443 from a Windows command prompt (i.e. cmd.exe, but can rename
2444 from Windows Explorer).
2447 if (!lp_delete_readonly(SNUM(conn))) {
2448 if (fattr & aRONLY) {
2449 return NT_STATUS_CANNOT_DELETE;
2453 /* On open checks the open itself will check the share mode, so
2454 don't do it here as we'll get it wrong. */
2456 status = SMB_VFS_CREATE_FILE
2459 0, /* root_dir_fid */
2461 0, /* create_file_flags */
2462 DELETE_ACCESS, /* access_mask */
2463 FILE_SHARE_NONE, /* share_access */
2464 FILE_OPEN, /* create_disposition*/
2465 FILE_NON_DIRECTORY_FILE, /* create_options */
2466 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2467 0, /* oplock_request */
2468 0, /* allocation_size */
2475 if (!NT_STATUS_IS_OK(status)) {
2476 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2477 nt_errstr(status)));
2481 /* The set is across all open files on this dev/inode pair. */
2482 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2483 close_file(req, fsp, NORMAL_CLOSE);
2484 return NT_STATUS_ACCESS_DENIED;
2487 return close_file(req, fsp, NORMAL_CLOSE);
2490 /****************************************************************************
2491 The guts of the unlink command, split out so it may be called by the NT SMB
2493 ****************************************************************************/
2495 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2496 uint32 dirtype, const char *name_in, bool has_wild)
2498 struct smb_filename *smb_fname = NULL;
2499 const char *directory = NULL;
2504 NTSTATUS status = NT_STATUS_OK;
2506 TALLOC_CTX *ctx = talloc_tos();
2508 status = unix_convert(ctx, conn, name_in, &smb_fname,
2509 has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
2510 if (!NT_STATUS_IS_OK(status)) {
2514 status = get_full_smb_filename(ctx, smb_fname, &name);
2515 if (!NT_STATUS_IS_OK(status)) {
2516 TALLOC_FREE(smb_fname);
2520 p = strrchr_m(name,'/');
2522 directory = talloc_strdup(ctx, ".");
2524 TALLOC_FREE(smb_fname);
2525 return NT_STATUS_NO_MEMORY;
2535 * We should only check the mangled cache
2536 * here if unix_convert failed. This means
2537 * that the path in 'mask' doesn't exist
2538 * on the file system and so we need to look
2539 * for a possible mangle. This patch from
2540 * Tine Smukavec <valentin.smukavec@hermes.si>.
2543 if (!VALID_STAT(smb_fname->st) && mangle_is_mangled(mask,conn->params)) {
2544 char *new_mask = NULL;
2545 mangle_lookup_name_from_8_3(ctx,
2553 TALLOC_FREE(smb_fname);
2556 directory = talloc_asprintf(ctx,
2561 return NT_STATUS_NO_MEMORY;
2564 dirtype = FILE_ATTRIBUTE_NORMAL;
2567 status = check_name(conn, directory);
2568 if (!NT_STATUS_IS_OK(status)) {
2572 status = do_unlink(conn, req, directory, dirtype);
2573 if (!NT_STATUS_IS_OK(status)) {
2579 struct smb_Dir *dir_hnd = NULL;
2583 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2584 return NT_STATUS_OBJECT_NAME_INVALID;
2587 if (strequal(mask,"????????.???")) {
2592 status = check_name(conn, directory);
2593 if (!NT_STATUS_IS_OK(status)) {
2597 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2599 if (dir_hnd == NULL) {
2600 return map_nt_error_from_unix(errno);
2603 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2604 the pattern matches against the long name, otherwise the short name
2605 We don't implement this yet XXXX
2608 status = NT_STATUS_NO_SUCH_FILE;
2610 while ((dname = ReadDirName(dir_hnd, &offset, &st))) {
2613 if (!is_visible_file(conn, directory, dname, &st,
2619 /* Quick check for "." and ".." */
2620 if (ISDOT(dname) || ISDOTDOT(dname)) {
2624 if(!mask_match(dname, mask, conn->case_sensitive)) {
2628 fname = talloc_asprintf(ctx, "%s/%s",
2632 return NT_STATUS_NO_MEMORY;
2635 status = check_name(conn, fname);
2636 if (!NT_STATUS_IS_OK(status)) {
2637 TALLOC_FREE(dir_hnd);
2641 status = do_unlink(conn, req, fname, dirtype);
2642 if (!NT_STATUS_IS_OK(status)) {
2648 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2653 TALLOC_FREE(dir_hnd);
2656 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2657 status = map_nt_error_from_unix(errno);
2663 /****************************************************************************
2665 ****************************************************************************/
2667 void reply_unlink(struct smb_request *req)
2669 connection_struct *conn = req->conn;
2673 bool path_contains_wcard = False;
2674 TALLOC_CTX *ctx = talloc_tos();
2676 START_PROFILE(SMBunlink);
2679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2680 END_PROFILE(SMBunlink);
2684 dirtype = SVAL(req->vwv+0, 0);
2686 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2687 STR_TERMINATE, &status,
2688 &path_contains_wcard);
2689 if (!NT_STATUS_IS_OK(status)) {
2690 reply_nterror(req, status);
2691 END_PROFILE(SMBunlink);
2695 status = resolve_dfspath_wcard(ctx, conn,
2696 req->flags2 & FLAGS2_DFS_PATHNAMES,
2699 &path_contains_wcard);
2700 if (!NT_STATUS_IS_OK(status)) {
2701 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2702 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2703 ERRSRV, ERRbadpath);
2704 END_PROFILE(SMBunlink);
2707 reply_nterror(req, status);
2708 END_PROFILE(SMBunlink);
2712 DEBUG(3,("reply_unlink : %s\n",name));
2714 status = unlink_internals(conn, req, dirtype, name,
2715 path_contains_wcard);
2716 if (!NT_STATUS_IS_OK(status)) {
2717 if (open_was_deferred(req->mid)) {
2718 /* We have re-scheduled this call. */
2719 END_PROFILE(SMBunlink);
2722 reply_nterror(req, status);
2723 END_PROFILE(SMBunlink);
2727 reply_outbuf(req, 0, 0);
2728 END_PROFILE(SMBunlink);
2733 /****************************************************************************
2735 ****************************************************************************/
2737 static void fail_readraw(void)
2739 const char *errstr = talloc_asprintf(talloc_tos(),
2740 "FAIL ! reply_readbraw: socket write fail (%s)",
2745 exit_server_cleanly(errstr);
2748 /****************************************************************************
2749 Fake (read/write) sendfile. Returns -1 on read or write fail.
2750 ****************************************************************************/
2752 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2756 size_t tosend = nread;
2763 bufsize = MIN(nread, 65536);
2765 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2769 while (tosend > 0) {
2773 if (tosend > bufsize) {
2778 ret = read_file(fsp,buf,startpos,cur_read);
2784 /* If we had a short read, fill with zeros. */
2785 if (ret < cur_read) {
2786 memset(buf + ret, '\0', cur_read - ret);
2789 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2794 startpos += cur_read;
2798 return (ssize_t)nread;
2801 #if defined(WITH_SENDFILE)
2802 /****************************************************************************
2803 Deal with the case of sendfile reading less bytes from the file than
2804 requested. Fill with zeros (all we can do).
2805 ****************************************************************************/
2807 static void sendfile_short_send(files_struct *fsp,
2812 #define SHORT_SEND_BUFSIZE 1024
2813 if (nread < headersize) {
2814 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2815 "header for file %s (%s). Terminating\n",
2816 fsp->fsp_name, strerror(errno) ));
2817 exit_server_cleanly("sendfile_short_send failed");
2820 nread -= headersize;
2822 if (nread < smb_maxcnt) {
2823 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2825 exit_server_cleanly("sendfile_short_send: "
2829 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2830 "with zeros !\n", fsp->fsp_name));
2832 while (nread < smb_maxcnt) {
2834 * We asked for the real file size and told sendfile
2835 * to not go beyond the end of the file. But it can
2836 * happen that in between our fstat call and the
2837 * sendfile call the file was truncated. This is very
2838 * bad because we have already announced the larger
2839 * number of bytes to the client.
2841 * The best we can do now is to send 0-bytes, just as
2842 * a read from a hole in a sparse file would do.
2844 * This should happen rarely enough that I don't care
2845 * about efficiency here :-)
2849 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2850 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2851 exit_server_cleanly("sendfile_short_send: "
2852 "write_data failed");
2859 #endif /* defined WITH_SENDFILE */
2861 /****************************************************************************
2862 Return a readbraw error (4 bytes of zero).
2863 ****************************************************************************/
2865 static void reply_readbraw_error(void)
2869 if (write_data(smbd_server_fd(),header,4) != 4) {
2874 /****************************************************************************
2875 Use sendfile in readbraw.
2876 ****************************************************************************/
2878 static void send_file_readbraw(connection_struct *conn,
2879 struct smb_request *req,
2885 char *outbuf = NULL;
2888 #if defined(WITH_SENDFILE)
2890 * We can only use sendfile on a non-chained packet
2891 * but we can use on a non-oplocked file. tridge proved this
2892 * on a train in Germany :-). JRA.
2893 * reply_readbraw has already checked the length.
2896 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2897 (fsp->wcp == NULL) &&
2898 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2899 ssize_t sendfile_read = -1;
2901 DATA_BLOB header_blob;
2903 _smb_setlen(header,nread);
2904 header_blob = data_blob_const(header, 4);
2906 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2907 &header_blob, startpos, nread)) == -1) {
2908 /* Returning ENOSYS means no data at all was sent.
2909 * Do this as a normal read. */
2910 if (errno == ENOSYS) {
2911 goto normal_readbraw;
2915 * Special hack for broken Linux with no working sendfile. If we
2916 * return EINTR we sent the header but not the rest of the data.
2917 * Fake this up by doing read/write calls.
2919 if (errno == EINTR) {
2920 /* Ensure we don't do this again. */
2921 set_use_sendfile(SNUM(conn), False);
2922 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2924 if (fake_sendfile(fsp, startpos, nread) == -1) {
2925 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2926 fsp->fsp_name, strerror(errno) ));
2927 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2932 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2933 fsp->fsp_name, strerror(errno) ));
2934 exit_server_cleanly("send_file_readbraw sendfile failed");
2935 } else if (sendfile_read == 0) {
2937 * Some sendfile implementations return 0 to indicate
2938 * that there was a short read, but nothing was
2939 * actually written to the socket. In this case,
2940 * fallback to the normal read path so the header gets
2941 * the correct byte count.
2943 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2944 "bytes falling back to the normal read: "
2945 "%s\n", fsp->fsp_name));
2946 goto normal_readbraw;
2949 /* Deal with possible short send. */
2950 if (sendfile_read != 4+nread) {
2951 sendfile_short_send(fsp, sendfile_read, 4, nread);
2959 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2961 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2962 (unsigned)(nread+4)));
2963 reply_readbraw_error();
2968 ret = read_file(fsp,outbuf+4,startpos,nread);
2969 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2978 _smb_setlen(outbuf,ret);
2979 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2982 TALLOC_FREE(outbuf);
2985 /****************************************************************************
2986 Reply to a readbraw (core+ protocol).
2987 ****************************************************************************/
2989 void reply_readbraw(struct smb_request *req)
2991 connection_struct *conn = req->conn;
2992 ssize_t maxcount,mincount;
2996 struct lock_struct lock;
3000 START_PROFILE(SMBreadbraw);
3002 if (srv_is_signing_active(smbd_server_conn) ||
3003 is_encrypted_packet(req->inbuf)) {
3004 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3005 "raw reads/writes are disallowed.");
3009 reply_readbraw_error();
3010 END_PROFILE(SMBreadbraw);
3015 * Special check if an oplock break has been issued
3016 * and the readraw request croses on the wire, we must
3017 * return a zero length response here.
3020 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3023 * We have to do a check_fsp by hand here, as
3024 * we must always return 4 zero bytes on error,
3028 if (!fsp || !conn || conn != fsp->conn ||
3029 req->vuid != fsp->vuid ||
3030 fsp->is_directory || fsp->fh->fd == -1) {
3032 * fsp could be NULL here so use the value from the packet. JRA.
3034 DEBUG(3,("reply_readbraw: fnum %d not valid "
3036 (int)SVAL(req->vwv+0, 0)));
3037 reply_readbraw_error();
3038 END_PROFILE(SMBreadbraw);
3042 /* Do a "by hand" version of CHECK_READ. */
3043 if (!(fsp->can_read ||
3044 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3045 (fsp->access_mask & FILE_EXECUTE)))) {
3046 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3047 (int)SVAL(req->vwv+0, 0)));
3048 reply_readbraw_error();
3049 END_PROFILE(SMBreadbraw);
3053 flush_write_cache(fsp, READRAW_FLUSH);
3055 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3056 if(req->wct == 10) {
3058 * This is a large offset (64 bit) read.
3060 #ifdef LARGE_SMB_OFF_T
3062 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3064 #else /* !LARGE_SMB_OFF_T */
3067 * Ensure we haven't been sent a >32 bit offset.
3070 if(IVAL(req->vwv+8, 0) != 0) {
3071 DEBUG(0,("reply_readbraw: large offset "
3072 "(%x << 32) used and we don't support "
3073 "64 bit offsets.\n",
3074 (unsigned int)IVAL(req->vwv+8, 0) ));
3075 reply_readbraw_error();
3076 END_PROFILE(SMBreadbraw);
3080 #endif /* LARGE_SMB_OFF_T */
3083 DEBUG(0,("reply_readbraw: negative 64 bit "
3084 "readraw offset (%.0f) !\n",
3085 (double)startpos ));
3086 reply_readbraw_error();
3087 END_PROFILE(SMBreadbraw);
3092 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3093 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3095 /* ensure we don't overrun the packet size */
3096 maxcount = MIN(65535,maxcount);
3098 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3099 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3102 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3103 reply_readbraw_error();
3104 END_PROFILE(SMBreadbraw);
3108 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3109 size = st.st_ex_size;
3112 if (startpos >= size) {
3115 nread = MIN(maxcount,(size - startpos));
3118 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3119 if (nread < mincount)
3123 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3124 "min=%lu nread=%lu\n",
3125 fsp->fnum, (double)startpos,
3126 (unsigned long)maxcount,
3127 (unsigned long)mincount,
3128 (unsigned long)nread ) );
3130 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3132 DEBUG(5,("reply_readbraw finished\n"));
3134 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3136 END_PROFILE(SMBreadbraw);
3141 #define DBGC_CLASS DBGC_LOCKING
3143 /****************************************************************************
3144 Reply to a lockread (core+ protocol).
3145 ****************************************************************************/
3147 void reply_lockread(struct smb_request *req)
3149 connection_struct *conn = req->conn;
3156 struct byte_range_lock *br_lck = NULL;
3158 struct smbd_server_connection *sconn = smbd_server_conn;
3160 START_PROFILE(SMBlockread);
3163 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3164 END_PROFILE(SMBlockread);
3168 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3170 if (!check_fsp(conn, req, fsp)) {
3171 END_PROFILE(SMBlockread);
3175 if (!CHECK_READ(fsp,req)) {
3176 reply_doserror(req, ERRDOS, ERRbadaccess);
3177 END_PROFILE(SMBlockread);
3181 numtoread = SVAL(req->vwv+1, 0);
3182 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3184 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3186 reply_outbuf(req, 5, numtoread + 3);
3188 data = smb_buf(req->outbuf) + 3;
3191 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3192 * protocol request that predates the read/write lock concept.
3193 * Thus instead of asking for a read lock here we need to ask
3194 * for a write lock. JRA.
3195 * Note that the requested lock size is unaffected by max_recv.
3198 br_lck = do_lock(smbd_messaging_context(),
3201 (uint64_t)numtoread,
3205 False, /* Non-blocking lock. */
3209 TALLOC_FREE(br_lck);
3211 if (NT_STATUS_V(status)) {
3212 reply_nterror(req, status);
3213 END_PROFILE(SMBlockread);
3218 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3221 if (numtoread > sconn->smb1.negprot.max_recv) {
3222 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3223 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3224 (unsigned int)numtoread,
3225 (unsigned int)sconn->smb1.negprot.max_recv));
3226 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3228 nread = read_file(fsp,data,startpos,numtoread);
3231 reply_unixerror(req, ERRDOS, ERRnoaccess);
3232 END_PROFILE(SMBlockread);
3236 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3238 SSVAL(req->outbuf,smb_vwv0,nread);
3239 SSVAL(req->outbuf,smb_vwv5,nread+3);
3240 p = smb_buf(req->outbuf);
3241 SCVAL(p,0,0); /* pad byte. */
3244 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3245 fsp->fnum, (int)numtoread, (int)nread));
3247 END_PROFILE(SMBlockread);
3252 #define DBGC_CLASS DBGC_ALL
3254 /****************************************************************************
3256 ****************************************************************************/
3258 void reply_read(struct smb_request *req)
3260 connection_struct *conn = req->conn;
3267 struct lock_struct lock;
3268 struct smbd_server_connection *sconn = smbd_server_conn;
3270 START_PROFILE(SMBread);
3273 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3274 END_PROFILE(SMBread);
3278 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3280 if (!check_fsp(conn, req, fsp)) {
3281 END_PROFILE(SMBread);
3285 if (!CHECK_READ(fsp,req)) {
3286 reply_doserror(req, ERRDOS, ERRbadaccess);
3287 END_PROFILE(SMBread);
3291 numtoread = SVAL(req->vwv+1, 0);
3292 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3294 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3297 * The requested read size cannot be greater than max_recv. JRA.
3299 if (numtoread > sconn->smb1.negprot.max_recv) {
3300 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3301 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3302 (unsigned int)numtoread,
3303 (unsigned int)sconn->smb1.negprot.max_recv));
3304 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3307 reply_outbuf(req, 5, numtoread+3);
3309 data = smb_buf(req->outbuf) + 3;
3311 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3312 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3315 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3316 reply_doserror(req, ERRDOS,ERRlock);
3317 END_PROFILE(SMBread);
3322 nread = read_file(fsp,data,startpos,numtoread);
3325 reply_unixerror(req, ERRDOS,ERRnoaccess);
3329 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3331 SSVAL(req->outbuf,smb_vwv0,nread);
3332 SSVAL(req->outbuf,smb_vwv5,nread+3);
3333 SCVAL(smb_buf(req->outbuf),0,1);
3334 SSVAL(smb_buf(req->outbuf),1,nread);
3336 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3337 fsp->fnum, (int)numtoread, (int)nread ) );
3340 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3342 END_PROFILE(SMBread);
3346 /****************************************************************************
3348 ****************************************************************************/
3350 static int setup_readX_header(struct smb_request *req, char *outbuf,
3356 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3357 data = smb_buf(outbuf);
3359 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3361 SCVAL(outbuf,smb_vwv0,0xFF);
3362 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3363 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3364 SSVAL(outbuf,smb_vwv6,
3366 + 1 /* the wct field */
3367 + 12 * sizeof(uint16_t) /* vwv */
3368 + 2); /* the buflen field */
3369 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3370 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3371 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3372 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3376 /****************************************************************************
3377 Reply to a read and X - possibly using sendfile.
3378 ****************************************************************************/
3380 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3381 files_struct *fsp, SMB_OFF_T startpos,
3384 SMB_STRUCT_STAT sbuf;
3386 struct lock_struct lock;
3388 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3389 reply_unixerror(req, ERRDOS, ERRnoaccess);
3393 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3394 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3397 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3398 reply_doserror(req, ERRDOS, ERRlock);
3402 if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
3403 || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
3405 * We already know that we would do a short read, so don't
3406 * try the sendfile() path.
3408 goto nosendfile_read;
3411 #if defined(WITH_SENDFILE)
3413 * We can only use sendfile on a non-chained packet
3414 * but we can use on a non-oplocked file. tridge proved this
3415 * on a train in Germany :-). JRA.
3418 if (!req_is_in_chain(req) &&
3419 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3420 (fsp->wcp == NULL) &&
3421 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3422 uint8 headerbuf[smb_size + 12 * 2];
3426 * Set up the packet header before send. We
3427 * assume here the sendfile will work (get the
3428 * correct amount of data).
3431 header = data_blob_const(headerbuf, sizeof(headerbuf));
3433 construct_reply_common_req(req, (char *)headerbuf);
3434 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3436 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3437 /* Returning ENOSYS means no data at all was sent.
3438 Do this as a normal read. */
3439 if (errno == ENOSYS) {
3444 * Special hack for broken Linux with no working sendfile. If we
3445 * return EINTR we sent the header but not the rest of the data.
3446 * Fake this up by doing read/write calls.
3449 if (errno == EINTR) {
3450 /* Ensure we don't do this again. */
3451 set_use_sendfile(SNUM(conn), False);
3452 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3453 nread = fake_sendfile(fsp, startpos,
3456 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3457 fsp->fsp_name, strerror(errno) ));
3458 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3460 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3461 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3462 /* No outbuf here means successful sendfile. */
3466 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3467 fsp->fsp_name, strerror(errno) ));
3468 exit_server_cleanly("send_file_readX sendfile failed");
3469 } else if (nread == 0) {
3471 * Some sendfile implementations return 0 to indicate
3472 * that there was a short read, but nothing was
3473 * actually written to the socket. In this case,
3474 * fallback to the normal read path so the header gets
3475 * the correct byte count.
3477 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3478 "falling back to the normal read: %s\n",
3483 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3484 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3486 /* Deal with possible short send. */
3487 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3488 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3490 /* No outbuf here means successful sendfile. */
3491 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3492 SMB_PERFCOUNT_END(&req->pcd);
3500 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3501 uint8 headerbuf[smb_size + 2*12];
3503 construct_reply_common_req(req, (char *)headerbuf);
3504 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3506 /* Send out the header. */
3507 if (write_data(smbd_server_fd(), (char *)headerbuf,
3508 sizeof(headerbuf)) != sizeof(headerbuf)) {
3509 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3510 fsp->fsp_name, strerror(errno) ));
3511 exit_server_cleanly("send_file_readX sendfile failed");
3513 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3515 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3516 fsp->fsp_name, strerror(errno) ));
3517 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3524 reply_outbuf(req, 12, smb_maxcnt);
3526 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3528 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3531 reply_unixerror(req, ERRDOS, ERRnoaccess);
3535 setup_readX_header(req, (char *)req->outbuf, nread);
3537 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3538 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3544 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3545 TALLOC_FREE(req->outbuf);
3549 /****************************************************************************
3550 Reply to a read and X.
3551 ****************************************************************************/
3553 void reply_read_and_X(struct smb_request *req)
3555 connection_struct *conn = req->conn;
3559 bool big_readX = False;
3561 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3564 START_PROFILE(SMBreadX);
3566 if ((req->wct != 10) && (req->wct != 12)) {
3567 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3571 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3572 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3573 smb_maxcnt = SVAL(req->vwv+5, 0);
3575 /* If it's an IPC, pass off the pipe handler. */
3577 reply_pipe_read_and_X(req);
3578 END_PROFILE(SMBreadX);
3582 if (!check_fsp(conn, req, fsp)) {
3583 END_PROFILE(SMBreadX);
3587 if (!CHECK_READ(fsp,req)) {
3588 reply_doserror(req, ERRDOS,ERRbadaccess);
3589 END_PROFILE(SMBreadX);
3593 if (global_client_caps & CAP_LARGE_READX) {
3594 size_t upper_size = SVAL(req->vwv+7, 0);
3595 smb_maxcnt |= (upper_size<<16);
3596 if (upper_size > 1) {
3597 /* Can't do this on a chained packet. */
3598 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3599 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3600 END_PROFILE(SMBreadX);
3603 /* We currently don't do this on signed or sealed data. */
3604 if (srv_is_signing_active(smbd_server_conn) ||
3605 is_encrypted_packet(req->inbuf)) {
3606 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3607 END_PROFILE(SMBreadX);
3610 /* Is there room in the reply for this data ? */
3611 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3613 NT_STATUS_INVALID_PARAMETER);
3614 END_PROFILE(SMBreadX);
3621 if (req->wct == 12) {
3622 #ifdef LARGE_SMB_OFF_T
3624 * This is a large offset (64 bit) read.
3626 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3628 #else /* !LARGE_SMB_OFF_T */
3631 * Ensure we haven't been sent a >32 bit offset.
3634 if(IVAL(req->vwv+10, 0) != 0) {
3635 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3636 "used and we don't support 64 bit offsets.\n",
3637 (unsigned int)IVAL(req->vwv+10, 0) ));
3638 END_PROFILE(SMBreadX);
3639 reply_doserror(req, ERRDOS, ERRbadaccess);
3643 #endif /* LARGE_SMB_OFF_T */
3648 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3652 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3655 END_PROFILE(SMBreadX);
3659 /****************************************************************************
3660 Error replies to writebraw must have smb_wct == 1. Fix this up.
3661 ****************************************************************************/
3663 void error_to_writebrawerr(struct smb_request *req)
3665 uint8 *old_outbuf = req->outbuf;
3667 reply_outbuf(req, 1, 0);
3669 memcpy(req->outbuf, old_outbuf, smb_size);
3670 TALLOC_FREE(old_outbuf);
3673 /****************************************************************************
3674 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3675 ****************************************************************************/
3677 void reply_writebraw(struct smb_request *req)
3679 connection_struct *conn = req->conn;
3682 ssize_t total_written=0;
3683 size_t numtowrite=0;
3689 struct lock_struct lock;
3692 START_PROFILE(SMBwritebraw);
3695 * If we ever reply with an error, it must have the SMB command
3696 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3699 SCVAL(req->inbuf,smb_com,SMBwritec);
3701 if (srv_is_signing_active(smbd_server_conn)) {
3702 END_PROFILE(SMBwritebraw);
3703 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3704 "raw reads/writes are disallowed.");
3707 if (req->wct < 12) {
3708 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3709 error_to_writebrawerr(req);
3710 END_PROFILE(SMBwritebraw);
3714 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3715 if (!check_fsp(conn, req, fsp)) {
3716 error_to_writebrawerr(req);
3717 END_PROFILE(SMBwritebraw);
3721 if (!CHECK_WRITE(fsp)) {
3722 reply_doserror(req, ERRDOS, ERRbadaccess);
3723 error_to_writebrawerr(req);
3724 END_PROFILE(SMBwritebraw);
3728 tcount = IVAL(req->vwv+1, 0);
3729 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3730 write_through = BITSETW(req->vwv+7,0);
3732 /* We have to deal with slightly different formats depending
3733 on whether we are using the core+ or lanman1.0 protocol */
3735 if(Protocol <= PROTOCOL_COREPLUS) {
3736 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3737 data = smb_buf(req->inbuf);
3739 numtowrite = SVAL(req->vwv+10, 0);
3740 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3743 /* Ensure we don't write bytes past the end of this packet. */
3744 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3745 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3746 error_to_writebrawerr(req);
3747 END_PROFILE(SMBwritebraw);
3751 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3752 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3755 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3756 reply_doserror(req, ERRDOS, ERRlock);
3757 error_to_writebrawerr(req);
3758 END_PROFILE(SMBwritebraw);
3763 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3766 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3767 "wrote=%d sync=%d\n",
3768 fsp->fnum, (double)startpos, (int)numtowrite,
3769 (int)nwritten, (int)write_through));
3771 if (nwritten < (ssize_t)numtowrite) {
3772 reply_unixerror(req, ERRHRD, ERRdiskfull);
3773 error_to_writebrawerr(req);
3777 total_written = nwritten;
3779 /* Allocate a buffer of 64k + length. */
3780 buf = TALLOC_ARRAY(NULL, char, 65540);
3782 reply_doserror(req, ERRDOS, ERRnomem);
3783 error_to_writebrawerr(req);
3787 /* Return a SMBwritebraw message to the redirector to tell
3788 * it to send more bytes */
3790 memcpy(buf, req->inbuf, smb_size);
3791 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3792 SCVAL(buf,smb_com,SMBwritebraw);
3793 SSVALS(buf,smb_vwv0,0xFFFF);
3795 if (!srv_send_smb(smbd_server_fd(),
3797 false, 0, /* no signing */
3798 IS_CONN_ENCRYPTED(conn),
3800 exit_server_cleanly("reply_writebraw: srv_send_smb "
3804 /* Now read the raw data into the buffer and write it */
3805 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3807 if (!NT_STATUS_IS_OK(status)) {
3808 exit_server_cleanly("secondary writebraw failed");
3811 /* Set up outbuf to return the correct size */
3812 reply_outbuf(req, 1, 0);
3814 if (numtowrite != 0) {
3816 if (numtowrite > 0xFFFF) {
3817 DEBUG(0,("reply_writebraw: Oversize secondary write "
3818 "raw requested (%u). Terminating\n",
3819 (unsigned int)numtowrite ));
3820 exit_server_cleanly("secondary writebraw failed");
3823 if (tcount > nwritten+numtowrite) {
3824 DEBUG(3,("reply_writebraw: Client overestimated the "
3826 (int)tcount,(int)nwritten,(int)numtowrite));
3829 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3831 if (!NT_STATUS_IS_OK(status)) {
3832 DEBUG(0,("reply_writebraw: Oversize secondary write "
3833 "raw read failed (%s). Terminating\n",
3834 nt_errstr(status)));
3835 exit_server_cleanly("secondary writebraw failed");
3838 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3839 if (nwritten == -1) {
3841 reply_unixerror(req, ERRHRD, ERRdiskfull);
3842 error_to_writebrawerr(req);
3846 if (nwritten < (ssize_t)numtowrite) {
3847 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3848 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3852 total_written += nwritten;
3857 SSVAL(req->outbuf,smb_vwv0,total_written);
3859 status = sync_file(conn, fsp, write_through);
3860 if (!NT_STATUS_IS_OK(status)) {
3861 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3862 fsp->fsp_name, nt_errstr(status) ));
3863 reply_nterror(req, status);
3864 error_to_writebrawerr(req);
3868 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3870 fsp->fnum, (double)startpos, (int)numtowrite,
3871 (int)total_written));
3873 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3875 /* We won't return a status if write through is not selected - this
3876 * follows what WfWg does */
3877 END_PROFILE(SMBwritebraw);
3879 if (!write_through && total_written==tcount) {
3881 #if RABBIT_PELLET_FIX
3883 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3884 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3887 if (!send_keepalive(smbd_server_fd())) {
3888 exit_server_cleanly("reply_writebraw: send of "
3889 "keepalive failed");
3892 TALLOC_FREE(req->outbuf);
3897 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3899 END_PROFILE(SMBwritebraw);
3904 #define DBGC_CLASS DBGC_LOCKING
3906 /****************************************************************************
3907 Reply to a writeunlock (core+).
3908 ****************************************************************************/
3910 void reply_writeunlock(struct smb_request *req)
3912 connection_struct *conn = req->conn;
3913 ssize_t nwritten = -1;
3917 NTSTATUS status = NT_STATUS_OK;
3919 struct lock_struct lock;
3921 START_PROFILE(SMBwriteunlock);
3924 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3925 END_PROFILE(SMBwriteunlock);
3929 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3931 if (!check_fsp(conn, req, fsp)) {
3932 END_PROFILE(SMBwriteunlock);
3936 if (!CHECK_WRITE(fsp)) {
3937 reply_doserror(req, ERRDOS,ERRbadaccess);
3938 END_PROFILE(SMBwriteunlock);
3942 numtowrite = SVAL(req->vwv+1, 0);
3943 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3944 data = (const char *)req->buf + 3;
3947 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3948 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3951 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3952 reply_doserror(req, ERRDOS, ERRlock);
3953 END_PROFILE(SMBwriteunlock);
3958 /* The special X/Open SMB protocol handling of
3959 zero length writes is *NOT* done for
3961 if(numtowrite == 0) {
3964 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3967 status = sync_file(conn, fsp, False /* write through */);
3968 if (!NT_STATUS_IS_OK(status)) {
3969 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3970 fsp->fsp_name, nt_errstr(status) ));
3971 reply_nterror(req, status);
3975 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3976 reply_unixerror(req, ERRHRD, ERRdiskfull);
3981 status = do_unlock(smbd_messaging_context(),
3984 (uint64_t)numtowrite,
3988 if (NT_STATUS_V(status)) {
3989 reply_nterror(req, status);
3994 reply_outbuf(req, 1, 0);
3996 SSVAL(req->outbuf,smb_vwv0,nwritten);
3998 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3999 fsp->fnum, (int)numtowrite, (int)nwritten));
4003 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4006 END_PROFILE(SMBwriteunlock);
4011 #define DBGC_CLASS DBGC_ALL
4013 /****************************************************************************
4015 ****************************************************************************/
4017 void reply_write(struct smb_request *req)
4019 connection_struct *conn = req->conn;
4021 ssize_t nwritten = -1;
4025 struct lock_struct lock;
4028 START_PROFILE(SMBwrite);
4031 END_PROFILE(SMBwrite);
4032 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4036 /* If it's an IPC, pass off the pipe handler. */
4038 reply_pipe_write(req);
4039 END_PROFILE(SMBwrite);
4043 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4045 if (!check_fsp(conn, req, fsp)) {
4046 END_PROFILE(SMBwrite);
4050 if (!CHECK_WRITE(fsp)) {
4051 reply_doserror(req, ERRDOS, ERRbadaccess);
4052 END_PROFILE(SMBwrite);
4056 numtowrite = SVAL(req->vwv+1, 0);
4057 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4058 data = (const char *)req->buf + 3;
4060 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4061 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4064 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4065 reply_doserror(req, ERRDOS, ERRlock);
4066 END_PROFILE(SMBwrite);
4071 * X/Open SMB protocol says that if smb_vwv1 is
4072 * zero then the file size should be extended or
4073 * truncated to the size given in smb_vwv[2-3].
4076 if(numtowrite == 0) {
4078 * This is actually an allocate call, and set EOF. JRA.
4080 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4082 reply_nterror(req, NT_STATUS_DISK_FULL);
4085 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4087 reply_nterror(req, NT_STATUS_DISK_FULL);
4090 trigger_write_time_update_immediate(fsp);
4092 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4095 status = sync_file(conn, fsp, False);
4096 if (!NT_STATUS_IS_OK(status)) {
4097 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4098 fsp->fsp_name, nt_errstr(status) ));
4099 reply_nterror(req, status);
4103 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4104 reply_unixerror(req, ERRHRD, ERRdiskfull);
4108 reply_outbuf(req, 1, 0);
4110 SSVAL(req->outbuf,smb_vwv0,nwritten);
4112 if (nwritten < (ssize_t)numtowrite) {
4113 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4114 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4117 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4120 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4122 END_PROFILE(SMBwrite);
4126 /****************************************************************************
4127 Ensure a buffer is a valid writeX for recvfile purposes.
4128 ****************************************************************************/
4130 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4131 (2*14) + /* word count (including bcc) */ \
4134 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4137 connection_struct *conn = NULL;
4138 unsigned int doff = 0;
4139 size_t len = smb_len_large(inbuf);
4141 if (is_encrypted_packet(inbuf)) {
4142 /* Can't do this on encrypted
4147 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4151 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4152 CVAL(inbuf,smb_wct) != 14) {
4153 DEBUG(10,("is_valid_writeX_buffer: chained or "
4154 "invalid word length.\n"));
4158 conn = conn_find(SVAL(inbuf, smb_tid));
4160 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4164 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4167 if (IS_PRINT(conn)) {
4168 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4171 doff = SVAL(inbuf,smb_vwv11);
4173 numtowrite = SVAL(inbuf,smb_vwv10);
4175 if (len > doff && len - doff > 0xFFFF) {
4176 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4179 if (numtowrite == 0) {
4180 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4184 /* Ensure the sizes match up. */
4185 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4186 /* no pad byte...old smbclient :-( */
4187 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4189 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4193 if (len - doff != numtowrite) {
4194 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4195 "len = %u, doff = %u, numtowrite = %u\n",
4198 (unsigned int)numtowrite ));
4202 DEBUG(10,("is_valid_writeX_buffer: true "
4203 "len = %u, doff = %u, numtowrite = %u\n",
4206 (unsigned int)numtowrite ));
4211 /****************************************************************************
4212 Reply to a write and X.
4213 ****************************************************************************/
4215 void reply_write_and_X(struct smb_request *req)
4217 connection_struct *conn = req->conn;
4219 struct lock_struct lock;
4224 unsigned int smb_doff;
4225 unsigned int smblen;
4229 START_PROFILE(SMBwriteX);
4231 if ((req->wct != 12) && (req->wct != 14)) {
4232 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4233 END_PROFILE(SMBwriteX);
4237 numtowrite = SVAL(req->vwv+10, 0);
4238 smb_doff = SVAL(req->vwv+11, 0);
4239 smblen = smb_len(req->inbuf);
4241 if (req->unread_bytes > 0xFFFF ||
4242 (smblen > smb_doff &&
4243 smblen - smb_doff > 0xFFFF)) {
4244 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4247 if (req->unread_bytes) {
4248 /* Can't do a recvfile write on IPC$ */
4250 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4251 END_PROFILE(SMBwriteX);
4254 if (numtowrite != req->unread_bytes) {
4255 reply_doserror(req, ERRDOS, ERRbadmem);
4256 END_PROFILE(SMBwriteX);
4260 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4261 smb_doff + numtowrite > smblen) {
4262 reply_doserror(req, ERRDOS, ERRbadmem);
4263 END_PROFILE(SMBwriteX);
4268 /* If it's an IPC, pass off the pipe handler. */
4270 if (req->unread_bytes) {
4271 reply_doserror(req, ERRDOS, ERRbadmem);
4272 END_PROFILE(SMBwriteX);
4275 reply_pipe_write_and_X(req);
4276 END_PROFILE(SMBwriteX);
4280 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4281 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4282 write_through = BITSETW(req->vwv+7,0);
4284 if (!check_fsp(conn, req, fsp)) {
4285 END_PROFILE(SMBwriteX);
4289 if (!CHECK_WRITE(fsp)) {
4290 reply_doserror(req, ERRDOS, ERRbadaccess);
4291 END_PROFILE(SMBwriteX);
4295 data = smb_base(req->inbuf) + smb_doff;
4297 if(req->wct == 14) {
4298 #ifdef LARGE_SMB_OFF_T
4300 * This is a large offset (64 bit) write.
4302 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4304 #else /* !LARGE_SMB_OFF_T */
4307 * Ensure we haven't been sent a >32 bit offset.
4310 if(IVAL(req->vwv+12, 0) != 0) {
4311 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4312 "used and we don't support 64 bit offsets.\n",
4313 (unsigned int)IVAL(req->vwv+12, 0) ));
4314 reply_doserror(req, ERRDOS, ERRbadaccess);
4315 END_PROFILE(SMBwriteX);
4319 #endif /* LARGE_SMB_OFF_T */
4322 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4323 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4326 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4327 reply_doserror(req, ERRDOS, ERRlock);
4328 END_PROFILE(SMBwriteX);
4332 /* X/Open SMB protocol says that, unlike SMBwrite
4333 if the length is zero then NO truncation is
4334 done, just a write of zero. To truncate a file,
4337 if(numtowrite == 0) {
4341 if ((req->unread_bytes == 0) &&
4342 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4347 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4350 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4351 reply_unixerror(req, ERRHRD, ERRdiskfull);
4355 reply_outbuf(req, 6, 0);
4356 SSVAL(req->outbuf,smb_vwv2,nwritten);
4357 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4359 if (nwritten < (ssize_t)numtowrite) {
4360 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4361 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4364 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4365 fsp->fnum, (int)numtowrite, (int)nwritten));
4367 status = sync_file(conn, fsp, write_through);
4368 if (!NT_STATUS_IS_OK(status)) {
4369 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4370 fsp->fsp_name, nt_errstr(status) ));
4371 reply_nterror(req, status);
4375 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4377 END_PROFILE(SMBwriteX);
4382 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4384 END_PROFILE(SMBwriteX);
4388 /****************************************************************************
4390 ****************************************************************************/
4392 void reply_lseek(struct smb_request *req)
4394 connection_struct *conn = req->conn;
4400 START_PROFILE(SMBlseek);
4403 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4404 END_PROFILE(SMBlseek);
4408 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4410 if (!check_fsp(conn, req, fsp)) {
4414 flush_write_cache(fsp, SEEK_FLUSH);
4416 mode = SVAL(req->vwv+1, 0) & 3;
4417 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4418 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4427 res = fsp->fh->pos + startpos;
4438 if (umode == SEEK_END) {
4439 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4440 if(errno == EINVAL) {
4441 SMB_OFF_T current_pos = startpos;
4442 SMB_STRUCT_STAT sbuf;
4444 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4445 reply_unixerror(req, ERRDOS,
4447 END_PROFILE(SMBlseek);
4451 current_pos += sbuf.st_ex_size;
4453 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4458 reply_unixerror(req, ERRDOS, ERRnoaccess);
4459 END_PROFILE(SMBlseek);
4466 reply_outbuf(req, 2, 0);
4467 SIVAL(req->outbuf,smb_vwv0,res);
4469 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4470 fsp->fnum, (double)startpos, (double)res, mode));
4472 END_PROFILE(SMBlseek);
4476 /****************************************************************************
4478 ****************************************************************************/
4480 void reply_flush(struct smb_request *req)
4482 connection_struct *conn = req->conn;
4486 START_PROFILE(SMBflush);
4489 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4493 fnum = SVAL(req->vwv+0, 0);
4494 fsp = file_fsp(req, fnum);
4496 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4501 file_sync_all(conn);
4503 NTSTATUS status = sync_file(conn, fsp, True);
4504 if (!NT_STATUS_IS_OK(status)) {
4505 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4506 fsp->fsp_name, nt_errstr(status) ));
4507 reply_nterror(req, status);
4508 END_PROFILE(SMBflush);
4513 reply_outbuf(req, 0, 0);
4515 DEBUG(3,("flush\n"));
4516 END_PROFILE(SMBflush);
4520 /****************************************************************************
4522 conn POINTER CAN BE NULL HERE !
4523 ****************************************************************************/
4525 void reply_exit(struct smb_request *req)
4527 START_PROFILE(SMBexit);
4529 file_close_pid(req->smbpid, req->vuid);
4531 reply_outbuf(req, 0, 0);
4533 DEBUG(3,("exit\n"));
4535 END_PROFILE(SMBexit);
4539 /****************************************************************************
4540 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4541 ****************************************************************************/
4543 void reply_close(struct smb_request *req)
4545 connection_struct *conn = req->conn;
4546 NTSTATUS status = NT_STATUS_OK;
4547 files_struct *fsp = NULL;
4548 START_PROFILE(SMBclose);
4551 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4552 END_PROFILE(SMBclose);
4556 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4559 * We can only use check_fsp if we know it's not a directory.
4562 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4563 reply_doserror(req, ERRDOS, ERRbadfid);
4564 END_PROFILE(SMBclose);
4568 if(fsp->is_directory) {
4570 * Special case - close NT SMB directory handle.
4572 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4573 status = close_file(req, fsp, NORMAL_CLOSE);
4577 * Close ordinary file.
4580 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4581 fsp->fh->fd, fsp->fnum,
4582 conn->num_files_open));
4585 * Take care of any time sent in the close.
4588 t = srv_make_unix_date3(req->vwv+1);
4589 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4592 * close_file() returns the unix errno if an error
4593 * was detected on close - normally this is due to
4594 * a disk full error. If not then it was probably an I/O error.
4597 status = close_file(req, fsp, NORMAL_CLOSE);
4600 if (!NT_STATUS_IS_OK(status)) {
4601 reply_nterror(req, status);
4602 END_PROFILE(SMBclose);
4606 reply_outbuf(req, 0, 0);
4607 END_PROFILE(SMBclose);
4611 /****************************************************************************
4612 Reply to a writeclose (Core+ protocol).
4613 ****************************************************************************/
4615 void reply_writeclose(struct smb_request *req)
4617 connection_struct *conn = req->conn;
4619 ssize_t nwritten = -1;
4620 NTSTATUS close_status = NT_STATUS_OK;
4623 struct timespec mtime;
4625 struct lock_struct lock;
4627 START_PROFILE(SMBwriteclose);
4630 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4631 END_PROFILE(SMBwriteclose);
4635 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4637 if (!check_fsp(conn, req, fsp)) {
4638 END_PROFILE(SMBwriteclose);
4641 if (!CHECK_WRITE(fsp)) {
4642 reply_doserror(req, ERRDOS,ERRbadaccess);
4643 END_PROFILE(SMBwriteclose);
4647 numtowrite = SVAL(req->vwv+1, 0);
4648 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4649 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4650 data = (const char *)req->buf + 1;
4653 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4654 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4657 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4658 reply_doserror(req, ERRDOS,ERRlock);
4659 END_PROFILE(SMBwriteclose);
4664 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4666 set_close_write_time(fsp, mtime);
4669 * More insanity. W2K only closes the file if writelen > 0.
4674 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4676 close_status = close_file(req, fsp, NORMAL_CLOSE);
4679 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4680 fsp->fnum, (int)numtowrite, (int)nwritten,
4681 conn->num_files_open));
4683 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4684 reply_doserror(req, ERRHRD, ERRdiskfull);
4688 if(!NT_STATUS_IS_OK(close_status)) {
4689 reply_nterror(req, close_status);
4693 reply_outbuf(req, 1, 0);
4695 SSVAL(req->outbuf,smb_vwv0,nwritten);
4699 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4702 END_PROFILE(SMBwriteclose);
4707 #define DBGC_CLASS DBGC_LOCKING
4709 /****************************************************************************
4711 ****************************************************************************/
4713 void reply_lock(struct smb_request *req)
4715 connection_struct *conn = req->conn;
4716 uint64_t count,offset;
4719 struct byte_range_lock *br_lck = NULL;
4721 START_PROFILE(SMBlock);
4724 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4725 END_PROFILE(SMBlock);
4729 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4731 if (!check_fsp(conn, req, fsp)) {
4732 END_PROFILE(SMBlock);
4736 count = (uint64_t)IVAL(req->vwv+1, 0);
4737 offset = (uint64_t)IVAL(req->vwv+3, 0);
4739 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4740 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4742 br_lck = do_lock(smbd_messaging_context(),
4749 False, /* Non-blocking lock. */
4754 TALLOC_FREE(br_lck);
4756 if (NT_STATUS_V(status)) {
4757 reply_nterror(req, status);
4758 END_PROFILE(SMBlock);
4762 reply_outbuf(req, 0, 0);
4764 END_PROFILE(SMBlock);
4768 /****************************************************************************
4770 ****************************************************************************/
4772 void reply_unlock(struct smb_request *req)
4774 connection_struct *conn = req->conn;
4775 uint64_t count,offset;
4779 START_PROFILE(SMBunlock);
4782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4783 END_PROFILE(SMBunlock);
4787 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4789 if (!check_fsp(conn, req, fsp)) {
4790 END_PROFILE(SMBunlock);
4794 count = (uint64_t)IVAL(req->vwv+1, 0);
4795 offset = (uint64_t)IVAL(req->vwv+3, 0);
4797 status = do_unlock(smbd_messaging_context(),
4804 if (NT_STATUS_V(status)) {
4805 reply_nterror(req, status);
4806 END_PROFILE(SMBunlock);
4810 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4811 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4813 reply_outbuf(req, 0, 0);
4815 END_PROFILE(SMBunlock);
4820 #define DBGC_CLASS DBGC_ALL
4822 /****************************************************************************
4824 conn POINTER CAN BE NULL HERE !
4825 ****************************************************************************/
4827 void reply_tdis(struct smb_request *req)
4829 connection_struct *conn = req->conn;
4830 START_PROFILE(SMBtdis);
4833 DEBUG(4,("Invalid connection in tdis\n"));
4834 reply_doserror(req, ERRSRV, ERRinvnid);
4835 END_PROFILE(SMBtdis);
4841 close_cnum(conn,req->vuid);
4844 reply_outbuf(req, 0, 0);
4845 END_PROFILE(SMBtdis);
4849 /****************************************************************************
4851 conn POINTER CAN BE NULL HERE !
4852 ****************************************************************************/
4854 void reply_echo(struct smb_request *req)
4856 connection_struct *conn = req->conn;
4857 struct smb_perfcount_data local_pcd;
4858 struct smb_perfcount_data *cur_pcd;
4862 START_PROFILE(SMBecho);
4864 smb_init_perfcount_data(&local_pcd);
4867 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4868 END_PROFILE(SMBecho);
4872 smb_reverb = SVAL(req->vwv+0, 0);
4874 reply_outbuf(req, 1, req->buflen);
4876 /* copy any incoming data back out */
4877 if (req->buflen > 0) {
4878 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4881 if (smb_reverb > 100) {
4882 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4886 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4888 /* this makes sure we catch the request pcd */
4889 if (seq_num == smb_reverb) {
4890 cur_pcd = &req->pcd;
4892 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4893 cur_pcd = &local_pcd;
4896 SSVAL(req->outbuf,smb_vwv0,seq_num);
4898 show_msg((char *)req->outbuf);
4899 if (!srv_send_smb(smbd_server_fd(),
4900 (char *)req->outbuf,
4901 true, req->seqnum+1,
4902 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4904 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4907 DEBUG(3,("echo %d times\n", smb_reverb));
4909 TALLOC_FREE(req->outbuf);
4911 END_PROFILE(SMBecho);
4915 /****************************************************************************
4916 Reply to a printopen.
4917 ****************************************************************************/
4919 void reply_printopen(struct smb_request *req)
4921 connection_struct *conn = req->conn;
4923 SMB_STRUCT_STAT sbuf;
4926 START_PROFILE(SMBsplopen);
4929 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4930 END_PROFILE(SMBsplopen);
4934 if (!CAN_PRINT(conn)) {
4935 reply_doserror(req, ERRDOS, ERRnoaccess);
4936 END_PROFILE(SMBsplopen);
4940 status = file_new(req, conn, &fsp);
4941 if(!NT_STATUS_IS_OK(status)) {
4942 reply_nterror(req, status);
4943 END_PROFILE(SMBsplopen);
4947 /* Open for exclusive use, write only. */
4948 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4950 if (!NT_STATUS_IS_OK(status)) {
4951 reply_nterror(req, status);
4952 END_PROFILE(SMBsplopen);
4956 reply_outbuf(req, 1, 0);
4957 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4959 DEBUG(3,("openprint fd=%d fnum=%d\n",
4960 fsp->fh->fd, fsp->fnum));
4962 END_PROFILE(SMBsplopen);
4966 /****************************************************************************
4967 Reply to a printclose.
4968 ****************************************************************************/
4970 void reply_printclose(struct smb_request *req)
4972 connection_struct *conn = req->conn;
4976 START_PROFILE(SMBsplclose);
4979 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4980 END_PROFILE(SMBsplclose);
4984 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4986 if (!check_fsp(conn, req, fsp)) {
4987 END_PROFILE(SMBsplclose);
4991 if (!CAN_PRINT(conn)) {
4992 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4993 END_PROFILE(SMBsplclose);
4997 DEBUG(3,("printclose fd=%d fnum=%d\n",
4998 fsp->fh->fd,fsp->fnum));
5000 status = close_file(req, fsp, NORMAL_CLOSE);
5002 if(!NT_STATUS_IS_OK(status)) {
5003 reply_nterror(req, status);
5004 END_PROFILE(SMBsplclose);
5008 reply_outbuf(req, 0, 0);
5010 END_PROFILE(SMBsplclose);
5014 /****************************************************************************
5015 Reply to a printqueue.
5016 ****************************************************************************/
5018 void reply_printqueue(struct smb_request *req)
5020 connection_struct *conn = req->conn;
5024 START_PROFILE(SMBsplretq);
5027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5028 END_PROFILE(SMBsplretq);
5032 max_count = SVAL(req->vwv+0, 0);
5033 start_index = SVAL(req->vwv+1, 0);
5035 /* we used to allow the client to get the cnum wrong, but that
5036 is really quite gross and only worked when there was only
5037 one printer - I think we should now only accept it if they
5038 get it right (tridge) */
5039 if (!CAN_PRINT(conn)) {
5040 reply_doserror(req, ERRDOS, ERRnoaccess);
5041 END_PROFILE(SMBsplretq);
5045 reply_outbuf(req, 2, 3);
5046 SSVAL(req->outbuf,smb_vwv0,0);
5047 SSVAL(req->outbuf,smb_vwv1,0);
5048 SCVAL(smb_buf(req->outbuf),0,1);
5049 SSVAL(smb_buf(req->outbuf),1,0);
5051 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5052 start_index, max_count));
5055 print_queue_struct *queue = NULL;
5056 print_status_struct status;
5057 int count = print_queue_status(SNUM(conn), &queue, &status);
5058 int num_to_get = ABS(max_count);
5059 int first = (max_count>0?start_index:start_index+max_count+1);
5065 num_to_get = MIN(num_to_get,count-first);
5068 for (i=first;i<first+num_to_get;i++) {
5072 srv_put_dos_date2(p,0,queue[i].time);
5073 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5074 SSVAL(p,5, queue[i].job);
5075 SIVAL(p,7,queue[i].size);
5077 srvstr_push(blob, req->flags2, p+12,
5078 queue[i].fs_user, 16, STR_ASCII);
5080 if (message_push_blob(
5083 blob, sizeof(blob))) == -1) {
5084 reply_nterror(req, NT_STATUS_NO_MEMORY);
5085 END_PROFILE(SMBsplretq);
5091 SSVAL(req->outbuf,smb_vwv0,count);
5092 SSVAL(req->outbuf,smb_vwv1,
5093 (max_count>0?first+count:first-1));
5094 SCVAL(smb_buf(req->outbuf),0,1);
5095 SSVAL(smb_buf(req->outbuf),1,28*count);
5100 DEBUG(3,("%d entries returned in queue\n",count));
5103 END_PROFILE(SMBsplretq);
5107 /****************************************************************************
5108 Reply to a printwrite.
5109 ****************************************************************************/
5111 void reply_printwrite(struct smb_request *req)
5113 connection_struct *conn = req->conn;
5118 START_PROFILE(SMBsplwr);
5121 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5122 END_PROFILE(SMBsplwr);
5126 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5128 if (!check_fsp(conn, req, fsp)) {
5129 END_PROFILE(SMBsplwr);
5133 if (!CAN_PRINT(conn)) {
5134 reply_doserror(req, ERRDOS, ERRnoaccess);
5135 END_PROFILE(SMBsplwr);
5139 if (!CHECK_WRITE(fsp)) {
5140 reply_doserror(req, ERRDOS, ERRbadaccess);
5141 END_PROFILE(SMBsplwr);
5145 numtowrite = SVAL(req->buf, 1);
5147 if (req->buflen < numtowrite + 3) {
5148 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5149 END_PROFILE(SMBsplwr);
5153 data = (const char *)req->buf + 3;
5155 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5156 reply_unixerror(req, ERRHRD, ERRdiskfull);
5157 END_PROFILE(SMBsplwr);
5161 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5163 END_PROFILE(SMBsplwr);
5167 /****************************************************************************
5169 ****************************************************************************/
5171 void reply_mkdir(struct smb_request *req)
5173 connection_struct *conn = req->conn;
5174 struct smb_filename *smb_dname = NULL;
5175 char *directory = NULL;
5177 TALLOC_CTX *ctx = talloc_tos();
5179 START_PROFILE(SMBmkdir);
5181 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5182 STR_TERMINATE, &status);
5183 if (!NT_STATUS_IS_OK(status)) {
5184 reply_nterror(req, status);
5188 status = resolve_dfspath(ctx, conn,
5189 req->flags2 & FLAGS2_DFS_PATHNAMES,
5192 if (!NT_STATUS_IS_OK(status)) {
5193 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5194 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5195 ERRSRV, ERRbadpath);
5198 reply_nterror(req, status);
5202 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
5203 if (!NT_STATUS_IS_OK(status)) {
5204 reply_nterror(req, status);
5208 status = get_full_smb_filename(ctx, smb_dname, &directory);
5209 if (!NT_STATUS_IS_OK(status)) {
5210 reply_nterror(req, status);
5214 status = check_name(conn, directory);
5215 if (!NT_STATUS_IS_OK(status)) {
5216 reply_nterror(req, status);
5220 status = create_directory(conn, req, directory);
5222 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5224 if (!NT_STATUS_IS_OK(status)) {
5226 if (!use_nt_status()
5227 && NT_STATUS_EQUAL(status,
5228 NT_STATUS_OBJECT_NAME_COLLISION)) {
5230 * Yes, in the DOS error code case we get a
5231 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5232 * samba4 torture test.
5234 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5237 reply_nterror(req, status);
5241 reply_outbuf(req, 0, 0);
5243 DEBUG( 3, ( "mkdir %s\n", directory ) );
5245 TALLOC_FREE(smb_dname);
5246 END_PROFILE(SMBmkdir);
5250 /****************************************************************************
5251 Static function used by reply_rmdir to delete an entire directory
5252 tree recursively. Return True on ok, False on fail.
5253 ****************************************************************************/
5255 static bool recursive_rmdir(TALLOC_CTX *ctx,
5256 connection_struct *conn,
5259 const char *dname = NULL;
5263 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5269 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5270 char *fullname = NULL;
5272 if (ISDOT(dname) || ISDOTDOT(dname)) {
5276 if (!is_visible_file(conn, directory, dname, &st, False)) {
5280 /* Construct the full name. */
5281 fullname = talloc_asprintf(ctx,
5291 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5296 if(st.st_ex_mode & S_IFDIR) {
5297 if(!recursive_rmdir(ctx, conn, fullname)) {
5301 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5305 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5309 TALLOC_FREE(fullname);
5311 TALLOC_FREE(dir_hnd);
5315 /****************************************************************************
5316 The internals of the rmdir code - called elsewhere.
5317 ****************************************************************************/
5319 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5320 connection_struct *conn,
5321 const char *directory)
5326 /* Might be a symlink. */
5327 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5328 return map_nt_error_from_unix(errno);
5331 if (S_ISLNK(st.st_ex_mode)) {
5332 /* Is what it points to a directory ? */
5333 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5334 return map_nt_error_from_unix(errno);
5336 if (!(S_ISDIR(st.st_ex_mode))) {
5337 return NT_STATUS_NOT_A_DIRECTORY;
5339 ret = SMB_VFS_UNLINK(conn,directory);
5341 ret = SMB_VFS_RMDIR(conn,directory);
5344 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5345 FILE_NOTIFY_CHANGE_DIR_NAME,
5347 return NT_STATUS_OK;
5350 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5352 * Check to see if the only thing in this directory are
5353 * vetoed files/directories. If so then delete them and
5354 * retry. If we fail to delete any of them (and we *don't*
5355 * do a recursive delete) then fail the rmdir.
5359 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5360 directory, NULL, 0);
5362 if(dir_hnd == NULL) {
5367 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5368 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5370 if (!is_visible_file(conn, directory, dname, &st, False))
5372 if(!IS_VETO_PATH(conn, dname)) {
5373 TALLOC_FREE(dir_hnd);
5379 /* We only have veto files/directories.
5380 * Are we allowed to delete them ? */
5382 if(!lp_recursive_veto_delete(SNUM(conn))) {
5383 TALLOC_FREE(dir_hnd);
5388 /* Do a recursive delete. */
5389 RewindDir(dir_hnd,&dirpos);
5390 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5391 char *fullname = NULL;
5393 if (ISDOT(dname) || ISDOTDOT(dname)) {
5396 if (!is_visible_file(conn, directory, dname, &st, False)) {
5400 fullname = talloc_asprintf(ctx,
5410 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5413 if(st.st_ex_mode & S_IFDIR) {
5414 if(!recursive_rmdir(ctx, conn, fullname)) {
5417 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5420 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5423 TALLOC_FREE(fullname);
5425 TALLOC_FREE(dir_hnd);
5426 /* Retry the rmdir */
5427 ret = SMB_VFS_RMDIR(conn,directory);
5433 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5434 "%s\n", directory,strerror(errno)));
5435 return map_nt_error_from_unix(errno);
5438 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5439 FILE_NOTIFY_CHANGE_DIR_NAME,
5442 return NT_STATUS_OK;
5445 /****************************************************************************
5447 ****************************************************************************/
5449 void reply_rmdir(struct smb_request *req)
5451 connection_struct *conn = req->conn;
5452 struct smb_filename *smb_dname = NULL;
5453 char *directory = NULL;
5455 TALLOC_CTX *ctx = talloc_tos();
5457 START_PROFILE(SMBrmdir);
5459 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5460 STR_TERMINATE, &status);
5461 if (!NT_STATUS_IS_OK(status)) {
5462 reply_nterror(req, status);
5466 status = resolve_dfspath(ctx, conn,
5467 req->flags2 & FLAGS2_DFS_PATHNAMES,
5470 if (!NT_STATUS_IS_OK(status)) {
5471 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5472 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5473 ERRSRV, ERRbadpath);
5476 reply_nterror(req, status);
5480 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
5481 if (!NT_STATUS_IS_OK(status)) {
5482 reply_nterror(req, status);
5486 status = get_full_smb_filename(ctx, smb_dname, &directory);
5487 if (!NT_STATUS_IS_OK(status)) {
5488 reply_nterror(req, status);
5492 status = check_name(conn, directory);
5493 if (!NT_STATUS_IS_OK(status)) {
5494 reply_nterror(req, status);
5498 dptr_closepath(directory, req->smbpid);
5499 status = rmdir_internals(ctx, conn, directory);
5500 if (!NT_STATUS_IS_OK(status)) {
5501 reply_nterror(req, status);
5505 reply_outbuf(req, 0, 0);
5507 DEBUG( 3, ( "rmdir %s\n", directory ) );
5509 TALLOC_FREE(smb_dname);
5510 END_PROFILE(SMBrmdir);
5514 /*******************************************************************
5515 Resolve wildcards in a filename rename.
5516 ********************************************************************/
5518 static bool resolve_wildcards(TALLOC_CTX *ctx,
5523 char *name2_copy = NULL;
5528 char *p,*p2, *pname1, *pname2;
5530 name2_copy = talloc_strdup(ctx, name2);
5535 pname1 = strrchr_m(name1,'/');
5536 pname2 = strrchr_m(name2_copy,'/');
5538 if (!pname1 || !pname2) {
5542 /* Truncate the copy of name2 at the last '/' */
5545 /* Now go past the '/' */
5549 root1 = talloc_strdup(ctx, pname1);
5550 root2 = talloc_strdup(ctx, pname2);
5552 if (!root1 || !root2) {
5556 p = strrchr_m(root1,'.');
5559 ext1 = talloc_strdup(ctx, p+1);
5561 ext1 = talloc_strdup(ctx, "");
5563 p = strrchr_m(root2,'.');
5566 ext2 = talloc_strdup(ctx, p+1);
5568 ext2 = talloc_strdup(ctx, "");
5571 if (!ext1 || !ext2) {
5579 /* Hmmm. Should this be mb-aware ? */
5582 } else if (*p2 == '*') {
5584 root2 = talloc_asprintf(ctx, "%s%s",
5603 /* Hmmm. Should this be mb-aware ? */
5606 } else if (*p2 == '*') {
5608 ext2 = talloc_asprintf(ctx, "%s%s",
5624 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5629 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5641 /****************************************************************************
5642 Ensure open files have their names updated. Updated to notify other smbd's
5644 ****************************************************************************/
5646 static void rename_open_files(connection_struct *conn,
5647 struct share_mode_lock *lck,
5648 const char *newname)
5651 bool did_rename = False;
5653 for(fsp = file_find_di_first(lck->id); fsp;
5654 fsp = file_find_di_next(fsp)) {
5655 /* fsp_name is a relative path under the fsp. To change this for other
5656 sharepaths we need to manipulate relative paths. */
5657 /* TODO - create the absolute path and manipulate the newname
5658 relative to the sharepath. */
5659 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5662 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5663 fsp->fnum, file_id_string_tos(&fsp->file_id),
5664 fsp->fsp_name, newname ));
5665 string_set(&fsp->fsp_name, newname);
5670 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5671 file_id_string_tos(&lck->id), newname ));
5674 /* Send messages to all smbd's (not ourself) that the name has changed. */
5675 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5679 /****************************************************************************
5680 We need to check if the source path is a parent directory of the destination
5681 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5682 refuse the rename with a sharing violation. Under UNIX the above call can
5683 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5684 probably need to check that the client is a Windows one before disallowing
5685 this as a UNIX client (one with UNIX extensions) can know the source is a
5686 symlink and make this decision intelligently. Found by an excellent bug
5687 report from <AndyLiebman@aol.com>.
5688 ****************************************************************************/
5690 static bool rename_path_prefix_equal(const char *src, const char *dest)
5692 const char *psrc = src;
5693 const char *pdst = dest;
5696 if (psrc[0] == '.' && psrc[1] == '/') {
5699 if (pdst[0] == '.' && pdst[1] == '/') {
5702 if ((slen = strlen(psrc)) > strlen(pdst)) {
5705 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5709 * Do the notify calls from a rename
5712 static void notify_rename(connection_struct *conn, bool is_dir,
5713 const char *oldpath, const char *newpath)
5715 char *olddir, *newdir;
5716 const char *oldname, *newname;
5719 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5720 : FILE_NOTIFY_CHANGE_FILE_NAME;
5722 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5723 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5724 TALLOC_FREE(olddir);
5728 if (strcmp(olddir, newdir) == 0) {
5729 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5730 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5733 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5734 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5736 TALLOC_FREE(olddir);
5737 TALLOC_FREE(newdir);
5739 /* this is a strange one. w2k3 gives an additional event for
5740 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5741 files, but not directories */
5743 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5744 FILE_NOTIFY_CHANGE_ATTRIBUTES
5745 |FILE_NOTIFY_CHANGE_CREATION,
5750 /****************************************************************************
5751 Rename an open file - given an fsp.
5752 ****************************************************************************/
5754 NTSTATUS rename_internals_fsp(connection_struct *conn,
5757 const char *newname_last_component,
5759 bool replace_if_exists)
5761 TALLOC_CTX *ctx = talloc_tos();
5762 SMB_STRUCT_STAT sbuf, sbuf1;
5763 NTSTATUS status = NT_STATUS_OK;
5764 struct share_mode_lock *lck = NULL;
5765 bool dst_exists, old_is_stream, new_is_stream;
5769 status = check_name(conn, newname);
5770 if (!NT_STATUS_IS_OK(status)) {
5774 /* Ensure newname contains a '/' */
5775 if(strrchr_m(newname,'/') == 0) {
5776 newname = talloc_asprintf(ctx,
5780 return NT_STATUS_NO_MEMORY;
5785 * Check for special case with case preserving and not
5786 * case sensitive. If the old last component differs from the original
5787 * last component only by case, then we should allow
5788 * the rename (user is trying to change the case of the
5792 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5793 strequal(newname, fsp->fsp_name)) {
5795 char *newname_modified_last_component = NULL;
5798 * Get the last component of the modified name.
5799 * Note that we guarantee that newname contains a '/'
5802 p = strrchr_m(newname,'/');
5803 newname_modified_last_component = talloc_strdup(ctx,
5805 if (!newname_modified_last_component) {
5806 return NT_STATUS_NO_MEMORY;
5809 if(strcsequal(newname_modified_last_component,
5810 newname_last_component) == False) {
5812 * Replace the modified last component with
5815 *p = '\0'; /* Truncate at the '/' */
5816 newname = talloc_asprintf(ctx,
5819 newname_last_component);
5824 * If the src and dest names are identical - including case,
5825 * don't do the rename, just return success.
5828 if (strcsequal(fsp->fsp_name, newname)) {
5829 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5831 return NT_STATUS_OK;
5834 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5835 new_is_stream = is_ntfs_stream_name(newname);
5837 /* Return the correct error code if both names aren't streams. */
5838 if (!old_is_stream && new_is_stream) {
5839 return NT_STATUS_OBJECT_NAME_INVALID;
5842 if (old_is_stream && !new_is_stream) {
5843 return NT_STATUS_INVALID_PARAMETER;
5847 * Have vfs_object_exist also fill sbuf1
5849 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5851 if(!replace_if_exists && dst_exists) {
5852 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5853 fsp->fsp_name,newname));
5854 return NT_STATUS_OBJECT_NAME_COLLISION;
5858 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5859 files_struct *dst_fsp = file_find_di_first(fileid);
5860 /* The file can be open when renaming a stream */
5861 if (dst_fsp && !new_is_stream) {
5862 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5863 return NT_STATUS_ACCESS_DENIED;
5867 /* Ensure we have a valid stat struct for the source. */
5868 if (fsp->fh->fd != -1) {
5869 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5870 return map_nt_error_from_unix(errno);
5874 if (fsp->posix_open) {
5875 ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
5877 ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
5880 return map_nt_error_from_unix(errno);
5884 status = can_rename(conn, fsp, attrs, &sbuf);
5886 if (!NT_STATUS_IS_OK(status)) {
5887 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5888 nt_errstr(status), fsp->fsp_name,newname));
5889 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5890 status = NT_STATUS_ACCESS_DENIED;
5894 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5895 return NT_STATUS_ACCESS_DENIED;
5898 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5902 * We have the file open ourselves, so not being able to get the
5903 * corresponding share mode lock is a fatal error.
5906 SMB_ASSERT(lck != NULL);
5908 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5909 uint32 create_options = fsp->fh->private_options;
5911 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5912 fsp->fsp_name,newname));
5914 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5916 rename_open_files(conn, lck, newname);
5919 * A rename acts as a new file create w.r.t. allowing an initial delete
5920 * on close, probably because in Windows there is a new handle to the
5921 * new file. If initial delete on close was requested but not
5922 * originally set, we need to set it here. This is probably not 100% correct,
5923 * but will work for the CIFSFS client which in non-posix mode
5924 * depends on these semantics. JRA.
5927 if (create_options & FILE_DELETE_ON_CLOSE) {
5928 status = can_set_delete_on_close(fsp, True, 0);
5930 if (NT_STATUS_IS_OK(status)) {
5931 /* Note that here we set the *inital* delete on close flag,
5932 * not the regular one. The magic gets handled in close. */
5933 fsp->initial_delete_on_close = True;
5937 return NT_STATUS_OK;
5942 if (errno == ENOTDIR || errno == EISDIR) {
5943 status = NT_STATUS_OBJECT_NAME_COLLISION;
5945 status = map_nt_error_from_unix(errno);
5948 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5949 nt_errstr(status), fsp->fsp_name,newname));
5954 /****************************************************************************
5955 The guts of the rename command, split out so it may be called by the NT SMB
5957 ****************************************************************************/
5959 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5960 connection_struct *conn,
5961 struct smb_request *req,
5962 const char *name_in,
5963 const char *newname_in,
5965 bool replace_if_exists,
5968 uint32_t access_mask)
5970 struct smb_filename *smb_fname = NULL;
5971 struct smb_filename *smb_fname_new = NULL;
5972 char *directory = NULL;
5975 char *newname = NULL;
5978 NTSTATUS status = NT_STATUS_OK;
5979 struct smb_Dir *dir_hnd = NULL;
5982 int create_options = 0;
5983 bool posix_pathnames = lp_posix_pathnames();
5985 status = unix_convert(ctx, conn, name_in, &smb_fname,
5986 src_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
5987 if (!NT_STATUS_IS_OK(status)) {
5991 status = get_full_smb_filename(ctx, smb_fname, &name);
5992 if (!NT_STATUS_IS_OK(status)) {
5996 status = unix_convert(ctx, conn, newname_in, &smb_fname_new,
5998 (dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0)));
5999 if (!NT_STATUS_IS_OK(status)) {
6003 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
6004 if (!NT_STATUS_IS_OK(status)) {
6009 * Split the old name into directory and last component
6010 * strings. Note that unix_convert may have stripped off a
6011 * leading ./ from both name and newname if the rename is
6012 * at the root of the share. We need to make sure either both
6013 * name and newname contain a / character or neither of them do
6014 * as this is checked in resolve_wildcards().
6017 p = strrchr_m(name,'/');
6019 directory = talloc_strdup(ctx, ".");
6021 status = NT_STATUS_NO_MEMORY;
6027 directory = talloc_strdup(ctx, name);
6029 status = NT_STATUS_NO_MEMORY;
6033 *p = '/'; /* Replace needed for exceptional test below. */
6037 * We should only check the mangled cache
6038 * here if unix_convert failed. This means
6039 * that the path in 'mask' doesn't exist
6040 * on the file system and so we need to look
6041 * for a possible mangle. This patch from
6042 * Tine Smukavec <valentin.smukavec@hermes.si>.
6045 if (!VALID_STAT(smb_fname->st) && mangle_is_mangled(mask, conn->params)) {
6046 char *new_mask = NULL;
6047 mangle_lookup_name_from_8_3(ctx,
6056 if (!src_has_wild) {
6060 * No wildcards - just process the one file.
6062 /* Add a terminating '/' to the directory name. */
6063 directory = talloc_asprintf_append(directory,
6067 status = NT_STATUS_NO_MEMORY;
6071 /* Ensure newname contains a '/' also */
6072 if(strrchr_m(newname,'/') == 0) {
6073 newname = talloc_asprintf(ctx,
6077 status = NT_STATUS_NO_MEMORY;
6082 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6083 "case_preserve = %d, short case preserve = %d, "
6084 "directory = %s, newname = %s, "
6085 "last_component_dest = %s\n",
6086 conn->case_sensitive, conn->case_preserve,
6087 conn->short_case_preserve, directory,
6088 newname, smb_fname_new->original_lcomp));
6090 /* The dest name still may have wildcards. */
6091 if (dest_has_wild) {
6092 char *mod_newname = NULL;
6093 if (!resolve_wildcards(ctx,
6094 directory,newname,&mod_newname)) {
6095 DEBUG(6, ("rename_internals: resolve_wildcards "
6099 status = NT_STATUS_NO_MEMORY;
6102 newname = mod_newname;
6105 ZERO_STRUCT(smb_fname->st);
6106 if (posix_pathnames) {
6107 SMB_VFS_LSTAT(conn, directory, &smb_fname->st);
6109 SMB_VFS_STAT(conn, directory, &smb_fname->st);
6112 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6113 create_options |= FILE_DIRECTORY_FILE;
6116 status = SMB_VFS_CREATE_FILE(
6119 0, /* root_dir_fid */
6120 directory, /* fname */
6121 0, /* create_file_flags */
6122 access_mask, /* access_mask */
6123 (FILE_SHARE_READ | /* share_access */
6125 FILE_OPEN, /* create_disposition*/
6126 create_options, /* create_options */
6127 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6128 0, /* oplock_request */
6129 0, /* allocation_size */
6134 &smb_fname->st); /* psbuf */
6136 if (!NT_STATUS_IS_OK(status)) {
6137 DEBUG(3, ("Could not open rename source %s: %s\n",
6138 directory, nt_errstr(status)));
6142 status = rename_internals_fsp(conn, fsp, newname,
6143 smb_fname_new->original_lcomp,
6144 attrs, replace_if_exists);
6146 close_file(req, fsp, NORMAL_CLOSE);
6148 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6149 nt_errstr(status), directory,newname));
6155 * Wildcards - process each file that matches.
6157 if (strequal(mask,"????????.???")) {
6162 status = check_name(conn, directory);
6163 if (!NT_STATUS_IS_OK(status)) {
6167 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
6168 if (dir_hnd == NULL) {
6169 status = map_nt_error_from_unix(errno);
6173 status = NT_STATUS_NO_SUCH_FILE;
6175 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6176 * - gentest fix. JRA
6179 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname->st))) {
6180 files_struct *fsp = NULL;
6182 char *destname = NULL;
6183 bool sysdir_entry = False;
6185 /* Quick check for "." and ".." */
6186 if (ISDOT(dname) || ISDOTDOT(dname)) {
6188 sysdir_entry = True;
6194 if (!is_visible_file(conn, directory, dname, &smb_fname->st,
6199 if(!mask_match(dname, mask, conn->case_sensitive)) {
6204 status = NT_STATUS_OBJECT_NAME_INVALID;
6208 fname = talloc_asprintf(ctx,
6213 status = NT_STATUS_NO_MEMORY;
6217 if (!resolve_wildcards(ctx,
6218 fname,newname,&destname)) {
6219 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6225 status = NT_STATUS_NO_MEMORY;
6229 ZERO_STRUCT(smb_fname->st);
6230 if (posix_pathnames) {
6231 SMB_VFS_LSTAT(conn, fname, &smb_fname->st);
6233 SMB_VFS_STAT(conn, fname, &smb_fname->st);
6238 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6239 create_options |= FILE_DIRECTORY_FILE;
6242 status = SMB_VFS_CREATE_FILE(
6245 0, /* root_dir_fid */
6247 0, /* create_file_flags */
6248 access_mask, /* access_mask */
6249 (FILE_SHARE_READ | /* share_access */
6251 FILE_OPEN, /* create_disposition*/
6252 create_options, /* create_options */
6253 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6254 0, /* oplock_request */
6255 0, /* allocation_size */
6260 &smb_fname->st); /* psbuf */
6262 if (!NT_STATUS_IS_OK(status)) {
6263 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6264 "returned %s rename %s -> %s\n",
6265 nt_errstr(status), directory, newname));
6269 status = rename_internals_fsp(conn, fsp, destname, dname,
6270 attrs, replace_if_exists);
6272 close_file(req, fsp, NORMAL_CLOSE);
6274 if (!NT_STATUS_IS_OK(status)) {
6275 DEBUG(3, ("rename_internals_fsp returned %s for "
6276 "rename %s -> %s\n", nt_errstr(status),
6277 directory, newname));
6283 DEBUG(3,("rename_internals: doing rename on %s -> "
6284 "%s\n",fname,destname));
6287 TALLOC_FREE(destname);
6289 TALLOC_FREE(dir_hnd);
6291 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6292 status = map_nt_error_from_unix(errno);
6296 TALLOC_FREE(smb_fname);
6297 TALLOC_FREE(smb_fname_new);
6301 /****************************************************************************
6303 ****************************************************************************/
6305 void reply_mv(struct smb_request *req)
6307 connection_struct *conn = req->conn;
6309 char *newname = NULL;
6313 bool src_has_wcard = False;
6314 bool dest_has_wcard = False;
6315 TALLOC_CTX *ctx = talloc_tos();
6317 START_PROFILE(SMBmv);
6320 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6325 attrs = SVAL(req->vwv+0, 0);
6327 p = (const char *)req->buf + 1;
6328 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6329 &status, &src_has_wcard);
6330 if (!NT_STATUS_IS_OK(status)) {
6331 reply_nterror(req, status);
6336 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6337 &status, &dest_has_wcard);
6338 if (!NT_STATUS_IS_OK(status)) {
6339 reply_nterror(req, status);
6344 status = resolve_dfspath_wcard(ctx, conn,
6345 req->flags2 & FLAGS2_DFS_PATHNAMES,
6349 if (!NT_STATUS_IS_OK(status)) {
6350 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6351 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6352 ERRSRV, ERRbadpath);
6356 reply_nterror(req, status);
6361 status = resolve_dfspath_wcard(ctx, conn,
6362 req->flags2 & FLAGS2_DFS_PATHNAMES,
6366 if (!NT_STATUS_IS_OK(status)) {
6367 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6368 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6369 ERRSRV, ERRbadpath);
6373 reply_nterror(req, status);
6378 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6380 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6381 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6382 if (!NT_STATUS_IS_OK(status)) {
6383 if (open_was_deferred(req->mid)) {
6384 /* We have re-scheduled this call. */
6388 reply_nterror(req, status);
6393 reply_outbuf(req, 0, 0);
6399 /*******************************************************************
6400 Copy a file as part of a reply_copy.
6401 ******************************************************************/
6404 * TODO: check error codes on all callers
6407 NTSTATUS copy_file(TALLOC_CTX *ctx,
6408 connection_struct *conn,
6413 bool target_is_directory)
6415 SMB_STRUCT_STAT src_sbuf, sbuf2;
6417 files_struct *fsp1,*fsp2;
6420 uint32 new_create_disposition;
6423 dest = talloc_strdup(ctx, dest1);
6425 return NT_STATUS_NO_MEMORY;
6427 if (target_is_directory) {
6428 const char *p = strrchr_m(src,'/');
6434 dest = talloc_asprintf_append(dest,
6438 return NT_STATUS_NO_MEMORY;
6442 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6444 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6447 if (!target_is_directory && count) {
6448 new_create_disposition = FILE_OPEN;
6450 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6451 NULL, NULL, &new_create_disposition, NULL)) {
6453 return NT_STATUS_INVALID_PARAMETER;
6457 status = SMB_VFS_CREATE_FILE(
6460 0, /* root_dir_fid */
6462 0, /* create_file_flags */
6463 FILE_GENERIC_READ, /* access_mask */
6464 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6465 FILE_OPEN, /* create_disposition*/
6466 0, /* create_options */
6467 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6468 INTERNAL_OPEN_ONLY, /* oplock_request */
6469 0, /* allocation_size */
6474 &src_sbuf); /* psbuf */
6476 if (!NT_STATUS_IS_OK(status)) {
6481 dosattrs = dos_mode(conn, src, &src_sbuf);
6482 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6483 ZERO_STRUCTP(&sbuf2);
6486 status = SMB_VFS_CREATE_FILE(
6489 0, /* root_dir_fid */
6491 0, /* create_file_flags */
6492 FILE_GENERIC_WRITE, /* access_mask */
6493 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6494 new_create_disposition, /* create_disposition*/
6495 0, /* create_options */
6496 dosattrs, /* file_attributes */
6497 INTERNAL_OPEN_ONLY, /* oplock_request */
6498 0, /* allocation_size */
6503 &sbuf2); /* psbuf */
6507 if (!NT_STATUS_IS_OK(status)) {
6508 close_file(NULL, fsp1, ERROR_CLOSE);
6512 if ((ofun&3) == 1) {
6513 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6514 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6516 * Stop the copy from occurring.
6519 src_sbuf.st_ex_size = 0;
6523 if (src_sbuf.st_ex_size) {
6524 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_ex_size);
6527 close_file(NULL, fsp1, NORMAL_CLOSE);
6529 /* Ensure the modtime is set correctly on the destination file. */
6530 set_close_write_time(fsp2, src_sbuf.st_ex_mtime);
6533 * As we are opening fsp1 read-only we only expect
6534 * an error on close on fsp2 if we are out of space.
6535 * Thus we don't look at the error return from the
6538 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6540 if (!NT_STATUS_IS_OK(status)) {
6544 if (ret != (SMB_OFF_T)src_sbuf.st_ex_size) {
6545 return NT_STATUS_DISK_FULL;
6548 return NT_STATUS_OK;
6551 /****************************************************************************
6552 Reply to a file copy.
6553 ****************************************************************************/
6555 void reply_copy(struct smb_request *req)
6557 connection_struct *conn = req->conn;
6558 struct smb_filename *smb_fname = NULL;
6559 struct smb_filename *smb_fname_new = NULL;
6561 char *newname = NULL;
6562 char *directory = NULL;
6563 const char *mask = NULL;
6564 const char mask_star[] = "*";
6567 int error = ERRnoaccess;
6572 bool target_is_directory=False;
6573 bool source_has_wild = False;
6574 bool dest_has_wild = False;
6576 TALLOC_CTX *ctx = talloc_tos();
6578 START_PROFILE(SMBcopy);
6581 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6585 tid2 = SVAL(req->vwv+0, 0);
6586 ofun = SVAL(req->vwv+1, 0);
6587 flags = SVAL(req->vwv+2, 0);
6589 p = (const char *)req->buf;
6590 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6591 &status, &source_has_wild);
6592 if (!NT_STATUS_IS_OK(status)) {
6593 reply_nterror(req, status);
6596 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6597 &status, &dest_has_wild);
6598 if (!NT_STATUS_IS_OK(status)) {
6599 reply_nterror(req, status);
6603 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6605 if (tid2 != conn->cnum) {
6606 /* can't currently handle inter share copies XXXX */
6607 DEBUG(3,("Rejecting inter-share copy\n"));
6608 reply_doserror(req, ERRSRV, ERRinvdevice);
6612 status = resolve_dfspath_wcard(ctx, conn,
6613 req->flags2 & FLAGS2_DFS_PATHNAMES,
6617 if (!NT_STATUS_IS_OK(status)) {
6618 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6619 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6620 ERRSRV, ERRbadpath);
6623 reply_nterror(req, status);
6627 status = resolve_dfspath_wcard(ctx, conn,
6628 req->flags2 & FLAGS2_DFS_PATHNAMES,
6632 if (!NT_STATUS_IS_OK(status)) {
6633 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6634 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6635 ERRSRV, ERRbadpath);
6638 reply_nterror(req, status);
6642 status = unix_convert(ctx, conn, name, &smb_fname,
6643 source_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6644 if (!NT_STATUS_IS_OK(status)) {
6645 reply_nterror(req, status);
6649 status = get_full_smb_filename(ctx, smb_fname, &name);
6650 if (!NT_STATUS_IS_OK(status)) {
6651 reply_nterror(req, status);
6655 status = unix_convert(ctx, conn, newname, &smb_fname_new,
6656 dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6657 if (!NT_STATUS_IS_OK(status)) {
6658 reply_nterror(req, status);
6662 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
6663 if (!NT_STATUS_IS_OK(status)) {
6664 reply_nterror(req, status);
6668 target_is_directory = VALID_STAT_OF_DIR(smb_fname_new->st);
6670 if ((flags&1) && target_is_directory) {
6671 reply_doserror(req, ERRDOS, ERRbadfile);
6675 if ((flags&2) && !target_is_directory) {
6676 reply_doserror(req, ERRDOS, ERRbadpath);
6680 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname->st)) {
6681 /* wants a tree copy! XXXX */
6682 DEBUG(3,("Rejecting tree copy\n"));
6683 reply_doserror(req, ERRSRV, ERRerror);
6687 p = strrchr_m(name,'/');
6689 directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
6692 directory = talloc_strdup(ctx, "./");
6697 reply_nterror(req, NT_STATUS_NO_MEMORY);
6702 * We should only check the mangled cache
6703 * here if unix_convert failed. This means
6704 * that the path in 'mask' doesn't exist
6705 * on the file system and so we need to look
6706 * for a possible mangle. This patch from
6707 * Tine Smukavec <valentin.smukavec@hermes.si>.
6710 if (!VALID_STAT(smb_fname->st) &&
6711 mangle_is_mangled(mask, conn->params)) {
6712 char *new_mask = NULL;
6713 mangle_lookup_name_from_8_3(ctx,
6722 if (!source_has_wild) {
6723 directory = talloc_asprintf_append(directory,
6726 if (dest_has_wild) {
6727 char *mod_newname = NULL;
6728 if (!resolve_wildcards(ctx,
6729 directory,newname,&mod_newname)) {
6730 reply_nterror(req, NT_STATUS_NO_MEMORY);
6733 newname = mod_newname;
6736 status = check_name(conn, directory);
6737 if (!NT_STATUS_IS_OK(status)) {
6738 reply_nterror(req, status);
6742 status = check_name(conn, newname);
6743 if (!NT_STATUS_IS_OK(status)) {
6744 reply_nterror(req, status);
6748 status = copy_file(ctx,conn,directory,newname,ofun,
6749 count,target_is_directory);
6751 if(!NT_STATUS_IS_OK(status)) {
6752 reply_nterror(req, status);
6758 struct smb_Dir *dir_hnd = NULL;
6759 const char *dname = NULL;
6762 if (strequal(mask,"????????.???")) {
6766 status = check_name(conn, directory);
6767 if (!NT_STATUS_IS_OK(status)) {
6768 reply_nterror(req, status);
6772 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6773 if (dir_hnd == NULL) {
6774 status = map_nt_error_from_unix(errno);
6775 reply_nterror(req, status);
6781 while ((dname = ReadDirName(dir_hnd, &offset,
6783 char *destname = NULL;
6786 if (ISDOT(dname) || ISDOTDOT(dname)) {
6790 if (!is_visible_file(conn, directory, dname,
6791 &smb_fname->st, False)) {
6795 if(!mask_match(dname, mask, conn->case_sensitive)) {
6799 error = ERRnoaccess;
6800 fname = talloc_asprintf(ctx,
6805 TALLOC_FREE(dir_hnd);
6806 reply_nterror(req, NT_STATUS_NO_MEMORY);
6810 if (!resolve_wildcards(ctx,
6811 fname,newname,&destname)) {
6815 TALLOC_FREE(dir_hnd);
6816 reply_nterror(req, NT_STATUS_NO_MEMORY);
6820 status = check_name(conn, fname);
6821 if (!NT_STATUS_IS_OK(status)) {
6822 TALLOC_FREE(dir_hnd);
6823 reply_nterror(req, status);
6827 status = check_name(conn, destname);
6828 if (!NT_STATUS_IS_OK(status)) {
6829 TALLOC_FREE(dir_hnd);
6830 reply_nterror(req, status);
6834 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6836 status = copy_file(ctx,conn,fname,destname,ofun,
6837 count,target_is_directory);
6838 if (NT_STATUS_IS_OK(status)) {
6842 TALLOC_FREE(destname);
6844 TALLOC_FREE(dir_hnd);
6849 /* Error on close... */
6851 reply_unixerror(req, ERRHRD, ERRgeneral);
6855 reply_doserror(req, ERRDOS, error);
6859 reply_outbuf(req, 1, 0);
6860 SSVAL(req->outbuf,smb_vwv0,count);
6862 TALLOC_FREE(smb_fname);
6863 TALLOC_FREE(smb_fname_new);
6864 END_PROFILE(SMBcopy);
6869 #define DBGC_CLASS DBGC_LOCKING
6871 /****************************************************************************
6872 Get a lock pid, dealing with large count requests.
6873 ****************************************************************************/
6875 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6876 bool large_file_format)
6878 if(!large_file_format)
6879 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6881 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6884 /****************************************************************************
6885 Get a lock count, dealing with large count requests.
6886 ****************************************************************************/
6888 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6889 bool large_file_format)
6893 if(!large_file_format) {
6894 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6897 #if defined(HAVE_LONGLONG)
6898 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6899 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6900 #else /* HAVE_LONGLONG */
6903 * NT4.x seems to be broken in that it sends large file (64 bit)
6904 * lockingX calls even if the CAP_LARGE_FILES was *not*
6905 * negotiated. For boxes without large unsigned ints truncate the
6906 * lock count by dropping the top 32 bits.
6909 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6910 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6911 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6912 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6913 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6916 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6917 #endif /* HAVE_LONGLONG */
6923 #if !defined(HAVE_LONGLONG)
6924 /****************************************************************************
6925 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6926 ****************************************************************************/
6928 static uint32 map_lock_offset(uint32 high, uint32 low)
6932 uint32 highcopy = high;
6935 * Try and find out how many significant bits there are in high.
6938 for(i = 0; highcopy; i++)
6942 * We use 31 bits not 32 here as POSIX
6943 * lock offsets may not be negative.
6946 mask = (~0) << (31 - i);
6949 return 0; /* Fail. */
6955 #endif /* !defined(HAVE_LONGLONG) */
6957 /****************************************************************************
6958 Get a lock offset, dealing with large offset requests.
6959 ****************************************************************************/
6961 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6962 bool large_file_format, bool *err)
6964 uint64_t offset = 0;
6968 if(!large_file_format) {
6969 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6972 #if defined(HAVE_LONGLONG)
6973 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6974 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6975 #else /* HAVE_LONGLONG */
6978 * NT4.x seems to be broken in that it sends large file (64 bit)
6979 * lockingX calls even if the CAP_LARGE_FILES was *not*
6980 * negotiated. For boxes without large unsigned ints mangle the
6981 * lock offset by mapping the top 32 bits onto the lower 32.
6984 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6985 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6986 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6989 if((new_low = map_lock_offset(high, low)) == 0) {
6991 return (uint64_t)-1;
6994 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6995 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6996 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6997 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7000 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7001 #endif /* HAVE_LONGLONG */
7007 /****************************************************************************
7008 Reply to a lockingX request.
7009 ****************************************************************************/
7011 void reply_lockingX(struct smb_request *req)
7013 connection_struct *conn = req->conn;
7015 unsigned char locktype;
7016 unsigned char oplocklevel;
7019 uint64_t count = 0, offset = 0;
7023 const uint8_t *data;
7024 bool large_file_format;
7026 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7028 START_PROFILE(SMBlockingX);
7031 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7032 END_PROFILE(SMBlockingX);
7036 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7037 locktype = CVAL(req->vwv+3, 0);
7038 oplocklevel = CVAL(req->vwv+3, 1);
7039 num_ulocks = SVAL(req->vwv+6, 0);
7040 num_locks = SVAL(req->vwv+7, 0);
7041 lock_timeout = IVAL(req->vwv+4, 0);
7042 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7044 if (!check_fsp(conn, req, fsp)) {
7045 END_PROFILE(SMBlockingX);
7051 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7052 /* we don't support these - and CANCEL_LOCK makes w2k
7053 and XP reboot so I don't really want to be
7054 compatible! (tridge) */
7055 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7056 END_PROFILE(SMBlockingX);
7060 /* Check if this is an oplock break on a file
7061 we have granted an oplock on.
7063 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7064 /* Client can insist on breaking to none. */
7065 bool break_to_none = (oplocklevel == 0);
7068 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7069 "for fnum = %d\n", (unsigned int)oplocklevel,
7073 * Make sure we have granted an exclusive or batch oplock on
7077 if (fsp->oplock_type == 0) {
7079 /* The Samba4 nbench simulator doesn't understand
7080 the difference between break to level2 and break
7081 to none from level2 - it sends oplock break
7082 replies in both cases. Don't keep logging an error
7083 message here - just ignore it. JRA. */
7085 DEBUG(5,("reply_lockingX: Error : oplock break from "
7086 "client for fnum = %d (oplock=%d) and no "
7087 "oplock granted on this file (%s).\n",
7088 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
7090 /* if this is a pure oplock break request then don't
7092 if (num_locks == 0 && num_ulocks == 0) {
7093 END_PROFILE(SMBlockingX);
7096 END_PROFILE(SMBlockingX);
7097 reply_doserror(req, ERRDOS, ERRlock);
7102 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7104 result = remove_oplock(fsp);
7106 result = downgrade_oplock(fsp);
7110 DEBUG(0, ("reply_lockingX: error in removing "
7111 "oplock on file %s\n", fsp->fsp_name));
7112 /* Hmmm. Is this panic justified? */
7113 smb_panic("internal tdb error");
7116 reply_to_oplock_break_requests(fsp);
7118 /* if this is a pure oplock break request then don't send a
7120 if (num_locks == 0 && num_ulocks == 0) {
7121 /* Sanity check - ensure a pure oplock break is not a
7123 if(CVAL(req->vwv+0, 0) != 0xff)
7124 DEBUG(0,("reply_lockingX: Error : pure oplock "
7125 "break is a chained %d request !\n",
7126 (unsigned int)CVAL(req->vwv+0, 0)));
7127 END_PROFILE(SMBlockingX);
7133 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7134 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7135 END_PROFILE(SMBlockingX);
7139 /* Data now points at the beginning of the list
7140 of smb_unlkrng structs */
7141 for(i = 0; i < (int)num_ulocks; i++) {
7142 lock_pid = get_lock_pid( data, i, large_file_format);
7143 count = get_lock_count( data, i, large_file_format);
7144 offset = get_lock_offset( data, i, large_file_format, &err);
7147 * There is no error code marked "stupid client bug".... :-).
7150 END_PROFILE(SMBlockingX);
7151 reply_doserror(req, ERRDOS, ERRnoaccess);
7155 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
7156 "pid %u, file %s\n", (double)offset, (double)count,
7157 (unsigned int)lock_pid, fsp->fsp_name ));
7159 status = do_unlock(smbd_messaging_context(),
7166 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
7167 nt_errstr(status)));
7169 if (NT_STATUS_V(status)) {
7170 END_PROFILE(SMBlockingX);
7171 reply_nterror(req, status);
7176 /* Setup the timeout in seconds. */
7178 if (!lp_blocking_locks(SNUM(conn))) {
7182 /* Now do any requested locks */
7183 data += ((large_file_format ? 20 : 10)*num_ulocks);
7185 /* Data now points at the beginning of the list
7186 of smb_lkrng structs */
7188 for(i = 0; i < (int)num_locks; i++) {
7189 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
7190 READ_LOCK:WRITE_LOCK);
7191 lock_pid = get_lock_pid( data, i, large_file_format);
7192 count = get_lock_count( data, i, large_file_format);
7193 offset = get_lock_offset( data, i, large_file_format, &err);
7196 * There is no error code marked "stupid client bug".... :-).
7199 END_PROFILE(SMBlockingX);
7200 reply_doserror(req, ERRDOS, ERRnoaccess);
7204 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
7205 "%u, file %s timeout = %d\n", (double)offset,
7206 (double)count, (unsigned int)lock_pid,
7207 fsp->fsp_name, (int)lock_timeout ));
7209 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7210 struct blocking_lock_record *blr = NULL;
7212 if (lp_blocking_locks(SNUM(conn))) {
7214 /* Schedule a message to ourselves to
7215 remove the blocking lock record and
7216 return the right error. */
7218 blr = blocking_lock_cancel(fsp,
7224 NT_STATUS_FILE_LOCK_CONFLICT);
7226 END_PROFILE(SMBlockingX);
7231 ERRcancelviolation));
7235 /* Remove a matching pending lock. */
7236 status = do_lock_cancel(fsp,
7243 bool blocking_lock = lock_timeout ? True : False;
7244 bool defer_lock = False;
7245 struct byte_range_lock *br_lck;
7246 uint32 block_smbpid;
7248 br_lck = do_lock(smbd_messaging_context(),
7260 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7261 /* Windows internal resolution for blocking locks seems
7262 to be about 200ms... Don't wait for less than that. JRA. */
7263 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7264 lock_timeout = lp_lock_spin_time();
7269 /* This heuristic seems to match W2K3 very well. If a
7270 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7271 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7272 far as I can tell. Replacement for do_lock_spin(). JRA. */
7274 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7275 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7277 lock_timeout = lp_lock_spin_time();
7280 if (br_lck && defer_lock) {
7282 * A blocking lock was requested. Package up
7283 * this smb into a queued request and push it
7284 * onto the blocking lock queue.
7286 if(push_blocking_lock_request(br_lck,
7297 TALLOC_FREE(br_lck);
7298 END_PROFILE(SMBlockingX);
7303 TALLOC_FREE(br_lck);
7306 if (NT_STATUS_V(status)) {
7307 END_PROFILE(SMBlockingX);
7308 reply_nterror(req, status);
7313 /* If any of the above locks failed, then we must unlock
7314 all of the previous locks (X/Open spec). */
7316 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7320 * Ensure we don't do a remove on the lock that just failed,
7321 * as under POSIX rules, if we have a lock already there, we
7322 * will delete it (and we shouldn't) .....
7324 for(i--; i >= 0; i--) {
7325 lock_pid = get_lock_pid( data, i, large_file_format);
7326 count = get_lock_count( data, i, large_file_format);
7327 offset = get_lock_offset( data, i, large_file_format,
7331 * There is no error code marked "stupid client
7335 END_PROFILE(SMBlockingX);
7336 reply_doserror(req, ERRDOS, ERRnoaccess);
7340 do_unlock(smbd_messaging_context(),
7347 END_PROFILE(SMBlockingX);
7348 reply_nterror(req, status);
7352 reply_outbuf(req, 2, 0);
7354 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7355 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7357 END_PROFILE(SMBlockingX);
7362 #define DBGC_CLASS DBGC_ALL
7364 /****************************************************************************
7365 Reply to a SMBreadbmpx (read block multiplex) request.
7366 Always reply with an error, if someone has a platform really needs this,
7367 please contact vl@samba.org
7368 ****************************************************************************/
7370 void reply_readbmpx(struct smb_request *req)
7372 START_PROFILE(SMBreadBmpx);
7373 reply_doserror(req, ERRSRV, ERRuseSTD);
7374 END_PROFILE(SMBreadBmpx);
7378 /****************************************************************************
7379 Reply to a SMBreadbs (read block multiplex secondary) request.
7380 Always reply with an error, if someone has a platform really needs this,
7381 please contact vl@samba.org
7382 ****************************************************************************/
7384 void reply_readbs(struct smb_request *req)
7386 START_PROFILE(SMBreadBs);
7387 reply_doserror(req, ERRSRV, ERRuseSTD);
7388 END_PROFILE(SMBreadBs);
7392 /****************************************************************************
7393 Reply to a SMBsetattrE.
7394 ****************************************************************************/
7396 void reply_setattrE(struct smb_request *req)
7398 connection_struct *conn = req->conn;
7399 struct smb_file_time ft;
7401 SMB_STRUCT_STAT sbuf;
7404 START_PROFILE(SMBsetattrE);
7408 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7409 END_PROFILE(SMBsetattrE);
7413 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7415 if(!fsp || (fsp->conn != conn)) {
7416 reply_doserror(req, ERRDOS, ERRbadfid);
7417 END_PROFILE(SMBsetattrE);
7423 * Convert the DOS times into unix times.
7426 ft.atime = convert_time_t_to_timespec(
7427 srv_make_unix_date2(req->vwv+3));
7428 ft.mtime = convert_time_t_to_timespec(
7429 srv_make_unix_date2(req->vwv+5));
7430 ft.create_time = convert_time_t_to_timespec(
7431 srv_make_unix_date2(req->vwv+1));
7433 reply_outbuf(req, 0, 0);
7436 * Patch from Ray Frush <frush@engr.colostate.edu>
7437 * Sometimes times are sent as zero - ignore them.
7440 /* Ensure we have a valid stat struct for the source. */
7441 if (fsp->fh->fd != -1) {
7442 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7443 status = map_nt_error_from_unix(errno);
7444 reply_nterror(req, status);
7445 END_PROFILE(SMBsetattrE);
7451 if (fsp->posix_open) {
7452 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
7454 ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
7457 status = map_nt_error_from_unix(errno);
7458 reply_nterror(req, status);
7459 END_PROFILE(SMBsetattrE);
7464 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7466 if (!NT_STATUS_IS_OK(status)) {
7467 reply_doserror(req, ERRDOS, ERRnoaccess);
7468 END_PROFILE(SMBsetattrE);
7472 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7475 (unsigned int)ft.atime.tv_sec,
7476 (unsigned int)ft.mtime.tv_sec,
7477 (unsigned int)ft.create_time.tv_sec
7480 END_PROFILE(SMBsetattrE);
7485 /* Back from the dead for OS/2..... JRA. */
7487 /****************************************************************************
7488 Reply to a SMBwritebmpx (write block multiplex primary) request.
7489 Always reply with an error, if someone has a platform really needs this,
7490 please contact vl@samba.org
7491 ****************************************************************************/
7493 void reply_writebmpx(struct smb_request *req)
7495 START_PROFILE(SMBwriteBmpx);
7496 reply_doserror(req, ERRSRV, ERRuseSTD);
7497 END_PROFILE(SMBwriteBmpx);
7501 /****************************************************************************
7502 Reply to a SMBwritebs (write block multiplex secondary) request.
7503 Always reply with an error, if someone has a platform really needs this,
7504 please contact vl@samba.org
7505 ****************************************************************************/
7507 void reply_writebs(struct smb_request *req)
7509 START_PROFILE(SMBwriteBs);
7510 reply_doserror(req, ERRSRV, ERRuseSTD);
7511 END_PROFILE(SMBwriteBs);
7515 /****************************************************************************
7516 Reply to a SMBgetattrE.
7517 ****************************************************************************/
7519 void reply_getattrE(struct smb_request *req)
7521 connection_struct *conn = req->conn;
7522 SMB_STRUCT_STAT sbuf;
7525 struct timespec create_ts;
7527 START_PROFILE(SMBgetattrE);
7530 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7531 END_PROFILE(SMBgetattrE);
7535 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7537 if(!fsp || (fsp->conn != conn)) {
7538 reply_doserror(req, ERRDOS, ERRbadfid);
7539 END_PROFILE(SMBgetattrE);
7543 /* Do an fstat on this file */
7544 if(fsp_stat(fsp, &sbuf)) {
7545 reply_unixerror(req, ERRDOS, ERRnoaccess);
7546 END_PROFILE(SMBgetattrE);
7550 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7553 * Convert the times into dos times. Set create
7554 * date to be last modify date as UNIX doesn't save
7558 reply_outbuf(req, 11, 0);
7560 create_ts = sbuf.st_ex_btime;
7561 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7562 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7563 convert_timespec_to_time_t(sbuf.st_ex_atime));
7564 /* Should we check pending modtime here ? JRA */
7565 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7566 convert_timespec_to_time_t(sbuf.st_ex_mtime));
7569 SIVAL(req->outbuf, smb_vwv6, 0);
7570 SIVAL(req->outbuf, smb_vwv8, 0);
7572 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7573 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_ex_size);
7574 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7576 SSVAL(req->outbuf,smb_vwv10, mode);
7578 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7580 END_PROFILE(SMBgetattrE);