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 /****************************************************************************
31 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
32 path or anything including wildcards.
33 We're assuming here that '/' is not the second byte in any multibyte char
34 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
36 ****************************************************************************/
38 /* Custom version for processing POSIX paths. */
39 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
41 static NTSTATUS check_path_syntax_internal(char *path,
43 bool *p_last_component_contains_wcard)
47 NTSTATUS ret = NT_STATUS_OK;
48 bool start_of_name_component = True;
49 bool stream_started = false;
51 *p_last_component_contains_wcard = False;
58 return NT_STATUS_OBJECT_NAME_INVALID;
61 return NT_STATUS_OBJECT_NAME_INVALID;
63 if (strchr_m(&s[1], ':')) {
64 return NT_STATUS_OBJECT_NAME_INVALID;
70 if (!posix_path && !stream_started && *s == ':') {
71 if (*p_last_component_contains_wcard) {
72 return NT_STATUS_OBJECT_NAME_INVALID;
74 /* Stream names allow more characters than file names.
75 We're overloading posix_path here to allow a wider
76 range of characters. If stream_started is true this
77 is still a Windows path even if posix_path is true.
80 stream_started = true;
81 start_of_name_component = false;
85 return NT_STATUS_OBJECT_NAME_INVALID;
89 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
91 * Safe to assume is not the second part of a mb char
92 * as this is handled below.
94 /* Eat multiple '/' or '\\' */
95 while (IS_PATH_SEP(*s,posix_path)) {
98 if ((d != path) && (*s != '\0')) {
99 /* We only care about non-leading or trailing '/' or '\\' */
103 start_of_name_component = True;
105 *p_last_component_contains_wcard = False;
109 if (start_of_name_component) {
110 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
111 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
114 * No mb char starts with '.' so we're safe checking the directory separator here.
117 /* If we just added a '/' - delete it */
118 if ((d > path) && (*(d-1) == '/')) {
123 /* Are we at the start ? Can't go back further if so. */
125 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
128 /* Go back one level... */
129 /* We know this is safe as '/' cannot be part of a mb sequence. */
130 /* NOTE - if this assumption is invalid we are not in good shape... */
131 /* Decrement d first as d points to the *next* char to write into. */
132 for (d--; d > path; d--) {
136 s += 2; /* Else go past the .. */
137 /* We're still at the start of a name component, just the previous one. */
140 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
152 if (*s <= 0x1f || *s == '|') {
153 return NT_STATUS_OBJECT_NAME_INVALID;
161 *p_last_component_contains_wcard = True;
170 /* Get the size of the next MB character. */
171 next_codepoint(s,&siz);
189 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
191 return NT_STATUS_INVALID_PARAMETER;
194 start_of_name_component = False;
202 /****************************************************************************
203 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
204 No wildcards allowed.
205 ****************************************************************************/
207 NTSTATUS check_path_syntax(char *path)
210 return check_path_syntax_internal(path, False, &ignore);
213 /****************************************************************************
214 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
215 Wildcards allowed - p_contains_wcard returns true if the last component contained
217 ****************************************************************************/
219 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
221 return check_path_syntax_internal(path, False, p_contains_wcard);
224 /****************************************************************************
225 Check the path for a POSIX client.
226 We're assuming here that '/' is not the second byte in any multibyte char
227 set (a safe assumption).
228 ****************************************************************************/
230 NTSTATUS check_path_syntax_posix(char *path)
233 return check_path_syntax_internal(path, True, &ignore);
236 /****************************************************************************
237 Pull a string and check the path allowing a wilcard - provide for error return.
238 ****************************************************************************/
240 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
241 const char *base_ptr,
248 bool *contains_wcard)
254 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
258 *err = NT_STATUS_INVALID_PARAMETER;
262 *contains_wcard = False;
264 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
266 * For a DFS path the function parse_dfs_path()
267 * will do the path processing, just make a copy.
273 if (lp_posix_pathnames()) {
274 *err = check_path_syntax_posix(*pp_dest);
276 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
282 /****************************************************************************
283 Pull a string and check the path - provide for error return.
284 ****************************************************************************/
286 size_t srvstr_get_path(TALLOC_CTX *ctx,
287 const char *base_ptr,
296 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
297 src_len, flags, err, &ignore);
300 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
301 char **pp_dest, const char *src, int flags,
302 NTSTATUS *err, bool *contains_wcard)
304 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
305 pp_dest, src, smbreq_bufrem(req, src),
306 flags, err, contains_wcard);
309 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
310 char **pp_dest, const char *src, int flags,
314 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
315 flags, err, &ignore);
318 /****************************************************************************
319 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
320 ****************************************************************************/
322 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
325 if (!(fsp) || !(conn)) {
326 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
329 if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
330 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
336 /****************************************************************************
337 Check if we have a correct fsp pointing to a file.
338 ****************************************************************************/
340 bool check_fsp(connection_struct *conn, struct smb_request *req,
343 if (!check_fsp_open(conn, req, fsp)) {
346 if ((fsp)->is_directory) {
347 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
350 if ((fsp)->fh->fd == -1) {
351 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
354 (fsp)->num_smb_operations++;
358 /****************************************************************************
359 Check if we have a correct fsp pointing to a quota fake file. Replacement for
360 the CHECK_NTQUOTA_HANDLE_OK macro.
361 ****************************************************************************/
363 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
366 if (!check_fsp_open(conn, req, fsp)) {
370 if (fsp->is_directory) {
374 if (fsp->fake_file_handle == NULL) {
378 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
382 if (fsp->fake_file_handle->private_data == NULL) {
389 /****************************************************************************
390 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
391 ****************************************************************************/
393 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
396 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
397 && (req->vuid == (fsp)->vuid)) {
401 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
405 static bool netbios_session_retarget(const char *name, int name_type)
408 char *trim_name_type;
409 const char *retarget_parm;
412 int retarget_type = 0x20;
413 int retarget_port = 139;
414 struct sockaddr_storage retarget_addr;
415 struct sockaddr_in *in_addr;
419 if (get_socket_port(smbd_server_fd()) != 139) {
423 trim_name = talloc_strdup(talloc_tos(), name);
424 if (trim_name == NULL) {
427 trim_char(trim_name, ' ', ' ');
429 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
431 if (trim_name_type == NULL) {
435 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
436 trim_name_type, NULL);
437 if (retarget_parm == NULL) {
438 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
441 if (retarget_parm == NULL) {
445 retarget = talloc_strdup(trim_name, retarget_parm);
446 if (retarget == NULL) {
450 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
452 p = strchr(retarget, ':');
455 retarget_port = atoi(p);
458 p = strchr_m(retarget, '#');
461 sscanf(p, "%x", &retarget_type);
464 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
466 DEBUG(10, ("could not resolve %s\n", retarget));
470 if (retarget_addr.ss_family != AF_INET) {
471 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
475 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
477 _smb_setlen(outbuf, 6);
478 SCVAL(outbuf, 0, 0x84);
479 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
480 *(uint16_t *)(outbuf+8) = htons(retarget_port);
482 if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
484 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
490 TALLOC_FREE(trim_name);
494 /****************************************************************************
495 Reply to a (netbios-level) special message.
496 ****************************************************************************/
498 void reply_special(char *inbuf)
500 int msg_type = CVAL(inbuf,0);
501 int msg_flags = CVAL(inbuf,1);
503 char name_type1, name_type2;
504 struct smbd_server_connection *sconn = smbd_server_conn;
507 * We only really use 4 bytes of the outbuf, but for the smb_setlen
508 * calculation & friends (srv_send_smb uses that) we need the full smb
511 char outbuf[smb_size];
515 memset(outbuf, '\0', sizeof(outbuf));
517 smb_setlen(outbuf,0);
520 case 0x81: /* session request */
522 if (sconn->nbt.got_session) {
523 exit_server_cleanly("multiple session request not permitted");
526 SCVAL(outbuf,0,0x82);
528 if (name_len(inbuf+4) > 50 ||
529 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
530 DEBUG(0,("Invalid name length in session request\n"));
533 name_type1 = name_extract(inbuf,4,name1);
534 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
535 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
536 name1, name_type1, name2, name_type2));
538 if (netbios_session_retarget(name1, name_type1)) {
539 exit_server_cleanly("retargeted client");
542 set_local_machine_name(name1, True);
543 set_remote_machine_name(name2, True);
545 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
546 get_local_machine_name(), get_remote_machine_name(),
549 if (name_type2 == 'R') {
550 /* We are being asked for a pathworks session ---
552 SCVAL(outbuf, 0,0x83);
556 /* only add the client's machine name to the list
557 of possibly valid usernames if we are operating
558 in share mode security */
559 if (lp_security() == SEC_SHARE) {
560 add_session_user(sconn, get_remote_machine_name());
563 reload_services(True);
566 sconn->nbt.got_session = true;
569 case 0x89: /* session keepalive request
570 (some old clients produce this?) */
571 SCVAL(outbuf,0,SMBkeepalive);
575 case 0x82: /* positive session response */
576 case 0x83: /* negative session response */
577 case 0x84: /* retarget session response */
578 DEBUG(0,("Unexpected session response\n"));
581 case SMBkeepalive: /* session keepalive */
586 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
587 msg_type, msg_flags));
589 srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
593 /****************************************************************************
595 conn POINTER CAN BE NULL HERE !
596 ****************************************************************************/
598 void reply_tcon(struct smb_request *req)
600 connection_struct *conn = req->conn;
602 char *service_buf = NULL;
603 char *password = NULL;
608 DATA_BLOB password_blob;
609 TALLOC_CTX *ctx = talloc_tos();
610 struct smbd_server_connection *sconn = smbd_server_conn;
612 START_PROFILE(SMBtcon);
614 if (req->buflen < 4) {
615 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
616 END_PROFILE(SMBtcon);
620 p = (const char *)req->buf + 1;
621 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
623 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
625 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
628 if (service_buf == NULL || password == NULL || dev == NULL) {
629 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
630 END_PROFILE(SMBtcon);
633 p = strrchr_m(service_buf,'\\');
637 service = service_buf;
640 password_blob = data_blob(password, pwlen+1);
642 conn = make_connection(sconn,service,password_blob,dev,
643 req->vuid,&nt_status);
646 data_blob_clear_free(&password_blob);
649 reply_nterror(req, nt_status);
650 END_PROFILE(SMBtcon);
654 reply_outbuf(req, 2, 0);
655 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
656 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
657 SSVAL(req->outbuf,smb_tid,conn->cnum);
659 DEBUG(3,("tcon service=%s cnum=%d\n",
660 service, conn->cnum));
662 END_PROFILE(SMBtcon);
666 /****************************************************************************
667 Reply to a tcon and X.
668 conn POINTER CAN BE NULL HERE !
669 ****************************************************************************/
671 void reply_tcon_and_X(struct smb_request *req)
673 connection_struct *conn = req->conn;
674 const char *service = NULL;
676 TALLOC_CTX *ctx = talloc_tos();
677 /* what the cleint thinks the device is */
678 char *client_devicetype = NULL;
679 /* what the server tells the client the share represents */
680 const char *server_devicetype;
686 struct smbd_server_connection *sconn = smbd_server_conn;
688 START_PROFILE(SMBtconX);
691 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
692 END_PROFILE(SMBtconX);
696 passlen = SVAL(req->vwv+3, 0);
697 tcon_flags = SVAL(req->vwv+2, 0);
699 /* we might have to close an old one */
700 if ((tcon_flags & 0x1) && conn) {
701 close_cnum(conn,req->vuid);
706 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
707 reply_doserror(req, ERRDOS, ERRbuftoosmall);
708 END_PROFILE(SMBtconX);
712 if (sconn->smb1.negprot.encrypted_passwords) {
713 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
714 if (lp_security() == SEC_SHARE) {
716 * Security = share always has a pad byte
717 * after the password.
719 p = (const char *)req->buf + passlen + 1;
721 p = (const char *)req->buf + passlen;
724 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
725 /* Ensure correct termination */
726 password.data[passlen]=0;
727 p = (const char *)req->buf + passlen + 1;
730 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
733 data_blob_clear_free(&password);
734 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
735 END_PROFILE(SMBtconX);
740 * the service name can be either: \\server\share
741 * or share directly like on the DELL PowerVault 705
744 q = strchr_m(path+2,'\\');
746 data_blob_clear_free(&password);
747 reply_doserror(req, ERRDOS, ERRnosuchshare);
748 END_PROFILE(SMBtconX);
756 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
757 &client_devicetype, p,
758 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
760 if (client_devicetype == NULL) {
761 data_blob_clear_free(&password);
762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
763 END_PROFILE(SMBtconX);
767 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
769 conn = make_connection(sconn, service, password, client_devicetype,
770 req->vuid, &nt_status);
773 data_blob_clear_free(&password);
776 reply_nterror(req, nt_status);
777 END_PROFILE(SMBtconX);
782 server_devicetype = "IPC";
783 else if ( IS_PRINT(conn) )
784 server_devicetype = "LPT1:";
786 server_devicetype = "A:";
788 if (get_Protocol() < PROTOCOL_NT1) {
789 reply_outbuf(req, 2, 0);
790 if (message_push_string(&req->outbuf, server_devicetype,
791 STR_TERMINATE|STR_ASCII) == -1) {
792 reply_nterror(req, NT_STATUS_NO_MEMORY);
793 END_PROFILE(SMBtconX);
797 /* NT sets the fstype of IPC$ to the null string */
798 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
800 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
801 /* Return permissions. */
805 reply_outbuf(req, 7, 0);
808 perm1 = FILE_ALL_ACCESS;
809 perm2 = FILE_ALL_ACCESS;
811 perm1 = CAN_WRITE(conn) ?
816 SIVAL(req->outbuf, smb_vwv3, perm1);
817 SIVAL(req->outbuf, smb_vwv5, perm2);
819 reply_outbuf(req, 3, 0);
822 if ((message_push_string(&req->outbuf, server_devicetype,
823 STR_TERMINATE|STR_ASCII) == -1)
824 || (message_push_string(&req->outbuf, fstype,
825 STR_TERMINATE) == -1)) {
826 reply_nterror(req, NT_STATUS_NO_MEMORY);
827 END_PROFILE(SMBtconX);
831 /* what does setting this bit do? It is set by NT4 and
832 may affect the ability to autorun mounted cdroms */
833 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
834 (lp_csc_policy(SNUM(conn)) << 2));
836 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
837 DEBUG(2,("Serving %s as a Dfs root\n",
838 lp_servicename(SNUM(conn)) ));
839 SSVAL(req->outbuf, smb_vwv2,
840 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
845 DEBUG(3,("tconX service=%s \n",
848 /* set the incoming and outgoing tid to the just created one */
849 SSVAL(req->inbuf,smb_tid,conn->cnum);
850 SSVAL(req->outbuf,smb_tid,conn->cnum);
852 END_PROFILE(SMBtconX);
854 req->tid = conn->cnum;
859 /****************************************************************************
860 Reply to an unknown type.
861 ****************************************************************************/
863 void reply_unknown_new(struct smb_request *req, uint8 type)
865 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
866 smb_fn_name(type), type, type));
867 reply_doserror(req, ERRSRV, ERRunknownsmb);
871 /****************************************************************************
873 conn POINTER CAN BE NULL HERE !
874 ****************************************************************************/
876 void reply_ioctl(struct smb_request *req)
878 connection_struct *conn = req->conn;
885 START_PROFILE(SMBioctl);
888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
889 END_PROFILE(SMBioctl);
893 device = SVAL(req->vwv+1, 0);
894 function = SVAL(req->vwv+2, 0);
895 ioctl_code = (device << 16) + function;
897 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
899 switch (ioctl_code) {
900 case IOCTL_QUERY_JOB_INFO:
904 reply_doserror(req, ERRSRV, ERRnosupport);
905 END_PROFILE(SMBioctl);
909 reply_outbuf(req, 8, replysize+1);
910 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
911 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
912 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
913 p = smb_buf(req->outbuf);
914 memset(p, '\0', replysize+1); /* valgrind-safe. */
915 p += 1; /* Allow for alignment */
917 switch (ioctl_code) {
918 case IOCTL_QUERY_JOB_INFO:
920 files_struct *fsp = file_fsp(
921 req, SVAL(req->vwv+0, 0));
923 reply_doserror(req, ERRDOS, ERRbadfid);
924 END_PROFILE(SMBioctl);
927 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
928 srvstr_push((char *)req->outbuf, req->flags2, p+2,
930 STR_TERMINATE|STR_ASCII);
932 srvstr_push((char *)req->outbuf, req->flags2,
933 p+18, lp_servicename(SNUM(conn)),
934 13, STR_TERMINATE|STR_ASCII);
942 END_PROFILE(SMBioctl);
946 /****************************************************************************
947 Strange checkpath NTSTATUS mapping.
948 ****************************************************************************/
950 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
952 /* Strange DOS error code semantics only for checkpath... */
953 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
954 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
955 /* We need to map to ERRbadpath */
956 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
962 /****************************************************************************
963 Reply to a checkpath.
964 ****************************************************************************/
966 void reply_checkpath(struct smb_request *req)
968 connection_struct *conn = req->conn;
969 struct smb_filename *smb_fname = NULL;
972 TALLOC_CTX *ctx = talloc_tos();
974 START_PROFILE(SMBcheckpath);
976 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
977 STR_TERMINATE, &status);
979 if (!NT_STATUS_IS_OK(status)) {
980 status = map_checkpath_error(req->flags2, status);
981 reply_nterror(req, status);
982 END_PROFILE(SMBcheckpath);
986 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
988 status = filename_convert(ctx,
990 req->flags2 & FLAGS2_DFS_PATHNAMES,
996 if (!NT_STATUS_IS_OK(status)) {
997 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
998 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1000 END_PROFILE(SMBcheckpath);
1006 if (!VALID_STAT(smb_fname->st) &&
1007 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1008 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1009 smb_fname_str_dbg(smb_fname), strerror(errno)));
1010 status = map_nt_error_from_unix(errno);
1014 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1015 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1016 ERRDOS, ERRbadpath);
1020 reply_outbuf(req, 0, 0);
1023 /* We special case this - as when a Windows machine
1024 is parsing a path is steps through the components
1025 one at a time - if a component fails it expects
1026 ERRbadpath, not ERRbadfile.
1028 status = map_checkpath_error(req->flags2, status);
1029 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1031 * Windows returns different error codes if
1032 * the parent directory is valid but not the
1033 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1034 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1035 * if the path is invalid.
1037 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1038 ERRDOS, ERRbadpath);
1042 reply_nterror(req, status);
1045 TALLOC_FREE(smb_fname);
1046 END_PROFILE(SMBcheckpath);
1050 /****************************************************************************
1052 ****************************************************************************/
1054 void reply_getatr(struct smb_request *req)
1056 connection_struct *conn = req->conn;
1057 struct smb_filename *smb_fname = NULL;
1064 TALLOC_CTX *ctx = talloc_tos();
1065 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1067 START_PROFILE(SMBgetatr);
1069 p = (const char *)req->buf + 1;
1070 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1071 if (!NT_STATUS_IS_OK(status)) {
1072 reply_nterror(req, status);
1076 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1077 under WfWg - weird! */
1078 if (*fname == '\0') {
1079 mode = aHIDDEN | aDIR;
1080 if (!CAN_WRITE(conn)) {
1086 status = filename_convert(ctx,
1088 req->flags2 & FLAGS2_DFS_PATHNAMES,
1093 if (!NT_STATUS_IS_OK(status)) {
1094 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1095 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1096 ERRSRV, ERRbadpath);
1099 reply_nterror(req, status);
1102 if (!VALID_STAT(smb_fname->st) &&
1103 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1104 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1105 smb_fname_str_dbg(smb_fname),
1107 reply_nterror(req, map_nt_error_from_unix(errno));
1111 mode = dos_mode(conn, smb_fname);
1112 size = smb_fname->st.st_ex_size;
1114 if (ask_sharemode) {
1115 struct timespec write_time_ts;
1116 struct file_id fileid;
1118 ZERO_STRUCT(write_time_ts);
1119 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1120 get_file_infos(fileid, NULL, &write_time_ts);
1121 if (!null_timespec(write_time_ts)) {
1122 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1126 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1132 reply_outbuf(req, 10, 0);
1134 SSVAL(req->outbuf,smb_vwv0,mode);
1135 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1136 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1138 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1140 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1142 if (get_Protocol() >= PROTOCOL_NT1) {
1143 SSVAL(req->outbuf, smb_flg2,
1144 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1147 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1148 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1151 TALLOC_FREE(smb_fname);
1153 END_PROFILE(SMBgetatr);
1157 /****************************************************************************
1159 ****************************************************************************/
1161 void reply_setatr(struct smb_request *req)
1163 struct smb_file_time ft;
1164 connection_struct *conn = req->conn;
1165 struct smb_filename *smb_fname = NULL;
1171 TALLOC_CTX *ctx = talloc_tos();
1173 START_PROFILE(SMBsetatr);
1178 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1182 p = (const char *)req->buf + 1;
1183 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1184 if (!NT_STATUS_IS_OK(status)) {
1185 reply_nterror(req, status);
1189 status = filename_convert(ctx,
1191 req->flags2 & FLAGS2_DFS_PATHNAMES,
1196 if (!NT_STATUS_IS_OK(status)) {
1197 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1198 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1199 ERRSRV, ERRbadpath);
1202 reply_nterror(req, status);
1206 if (smb_fname->base_name[0] == '.' &&
1207 smb_fname->base_name[1] == '\0') {
1209 * Not sure here is the right place to catch this
1210 * condition. Might be moved to somewhere else later -- vl
1212 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1216 mode = SVAL(req->vwv+0, 0);
1217 mtime = srv_make_unix_date3(req->vwv+1);
1219 ft.mtime = convert_time_t_to_timespec(mtime);
1220 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1221 if (!NT_STATUS_IS_OK(status)) {
1222 reply_nterror(req, status);
1226 if (mode != FILE_ATTRIBUTE_NORMAL) {
1227 if (VALID_STAT_OF_DIR(smb_fname->st))
1232 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1234 reply_nterror(req, map_nt_error_from_unix(errno));
1239 reply_outbuf(req, 0, 0);
1241 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1244 TALLOC_FREE(smb_fname);
1245 END_PROFILE(SMBsetatr);
1249 /****************************************************************************
1251 ****************************************************************************/
1253 void reply_dskattr(struct smb_request *req)
1255 connection_struct *conn = req->conn;
1256 uint64_t dfree,dsize,bsize;
1257 START_PROFILE(SMBdskattr);
1259 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1260 reply_nterror(req, map_nt_error_from_unix(errno));
1261 END_PROFILE(SMBdskattr);
1265 reply_outbuf(req, 5, 0);
1267 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1268 double total_space, free_space;
1269 /* we need to scale this to a number that DOS6 can handle. We
1270 use floating point so we can handle large drives on systems
1271 that don't have 64 bit integers
1273 we end up displaying a maximum of 2G to DOS systems
1275 total_space = dsize * (double)bsize;
1276 free_space = dfree * (double)bsize;
1278 dsize = (uint64_t)((total_space+63*512) / (64*512));
1279 dfree = (uint64_t)((free_space+63*512) / (64*512));
1281 if (dsize > 0xFFFF) dsize = 0xFFFF;
1282 if (dfree > 0xFFFF) dfree = 0xFFFF;
1284 SSVAL(req->outbuf,smb_vwv0,dsize);
1285 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1286 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1287 SSVAL(req->outbuf,smb_vwv3,dfree);
1289 SSVAL(req->outbuf,smb_vwv0,dsize);
1290 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1291 SSVAL(req->outbuf,smb_vwv2,512);
1292 SSVAL(req->outbuf,smb_vwv3,dfree);
1295 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1297 END_PROFILE(SMBdskattr);
1302 * Utility function to split the filename from the directory.
1304 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1305 char **fname_dir_out,
1306 char **fname_mask_out)
1308 const char *p = NULL;
1309 char *fname_dir = NULL;
1310 char *fname_mask = NULL;
1312 p = strrchr_m(fname_in, '/');
1314 fname_dir = talloc_strdup(ctx, ".");
1315 fname_mask = talloc_strdup(ctx, fname_in);
1317 fname_dir = talloc_strndup(ctx, fname_in,
1318 PTR_DIFF(p, fname_in));
1319 fname_mask = talloc_strdup(ctx, p+1);
1322 if (!fname_dir || !fname_mask) {
1323 TALLOC_FREE(fname_dir);
1324 TALLOC_FREE(fname_mask);
1325 return NT_STATUS_NO_MEMORY;
1328 *fname_dir_out = fname_dir;
1329 *fname_mask_out = fname_mask;
1330 return NT_STATUS_OK;
1333 /****************************************************************************
1335 Can be called from SMBsearch, SMBffirst or SMBfunique.
1336 ****************************************************************************/
1338 void reply_search(struct smb_request *req)
1340 connection_struct *conn = req->conn;
1342 const char *mask = NULL;
1343 char *directory = NULL;
1344 struct smb_filename *smb_fname = NULL;
1348 struct timespec date;
1350 unsigned int numentries = 0;
1351 unsigned int maxentries = 0;
1352 bool finished = False;
1357 bool check_descend = False;
1358 bool expect_close = False;
1360 bool mask_contains_wcard = False;
1361 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1362 TALLOC_CTX *ctx = talloc_tos();
1363 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1364 struct dptr_struct *dirptr = NULL;
1365 struct smbd_server_connection *sconn = smbd_server_conn;
1367 START_PROFILE(SMBsearch);
1370 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1374 if (lp_posix_pathnames()) {
1375 reply_unknown_new(req, req->cmd);
1379 /* If we were called as SMBffirst then we must expect close. */
1380 if(req->cmd == SMBffirst) {
1381 expect_close = True;
1384 reply_outbuf(req, 1, 3);
1385 maxentries = SVAL(req->vwv+0, 0);
1386 dirtype = SVAL(req->vwv+1, 0);
1387 p = (const char *)req->buf + 1;
1388 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1389 &nt_status, &mask_contains_wcard);
1390 if (!NT_STATUS_IS_OK(nt_status)) {
1391 reply_nterror(req, nt_status);
1396 status_len = SVAL(p, 0);
1399 /* dirtype &= ~aDIR; */
1401 if (status_len == 0) {
1402 nt_status = filename_convert(ctx, conn,
1403 req->flags2 & FLAGS2_DFS_PATHNAMES,
1405 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1406 &mask_contains_wcard,
1408 if (!NT_STATUS_IS_OK(nt_status)) {
1409 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1410 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1411 ERRSRV, ERRbadpath);
1414 reply_nterror(req, nt_status);
1418 directory = smb_fname->base_name;
1420 p = strrchr_m(directory,'/');
1421 if ((p != NULL) && (*directory != '/')) {
1423 directory = talloc_strndup(ctx, directory,
1424 PTR_DIFF(p, directory));
1427 directory = talloc_strdup(ctx,".");
1431 reply_nterror(req, NT_STATUS_NO_MEMORY);
1435 memset((char *)status,'\0',21);
1436 SCVAL(status,0,(dirtype & 0x1F));
1438 nt_status = dptr_create(conn,
1444 mask_contains_wcard,
1447 if (!NT_STATUS_IS_OK(nt_status)) {
1448 reply_nterror(req, nt_status);
1451 dptr_num = dptr_dnum(dirptr);
1454 const char *dirpath;
1456 memcpy(status,p,21);
1457 status_dirtype = CVAL(status,0) & 0x1F;
1458 if (status_dirtype != (dirtype & 0x1F)) {
1459 dirtype = status_dirtype;
1462 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1466 dirpath = dptr_path(sconn, dptr_num);
1467 directory = talloc_strdup(ctx, dirpath);
1469 reply_nterror(req, NT_STATUS_NO_MEMORY);
1473 mask = dptr_wcard(sconn, dptr_num);
1478 * For a 'continue' search we have no string. So
1479 * check from the initial saved string.
1481 mask_contains_wcard = ms_has_wild(mask);
1482 dirtype = dptr_attr(sconn, dptr_num);
1485 DEBUG(4,("dptr_num is %d\n",dptr_num));
1487 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1488 dptr_init_search_op(dirptr);
1490 if ((dirtype&0x1F) == aVOLID) {
1491 char buf[DIR_STRUCT_SIZE];
1492 memcpy(buf,status,21);
1493 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1494 0,aVOLID,0,!allow_long_path_components)) {
1495 reply_nterror(req, NT_STATUS_NO_MEMORY);
1498 dptr_fill(sconn, buf+12,dptr_num);
1499 if (dptr_zero(buf+12) && (status_len==0)) {
1504 if (message_push_blob(&req->outbuf,
1505 data_blob_const(buf, sizeof(buf)))
1507 reply_nterror(req, NT_STATUS_NO_MEMORY);
1515 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1518 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1519 directory,lp_dontdescend(SNUM(conn))));
1520 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1521 check_descend = True;
1524 for (i=numentries;(i<maxentries) && !finished;i++) {
1525 finished = !get_dir_entry(ctx,
1536 char buf[DIR_STRUCT_SIZE];
1537 memcpy(buf,status,21);
1538 if (!make_dir_struct(ctx,
1544 convert_timespec_to_time_t(date),
1545 !allow_long_path_components)) {
1546 reply_nterror(req, NT_STATUS_NO_MEMORY);
1549 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1552 if (message_push_blob(&req->outbuf,
1553 data_blob_const(buf, sizeof(buf)))
1555 reply_nterror(req, NT_STATUS_NO_MEMORY);
1565 /* If we were called as SMBffirst with smb_search_id == NULL
1566 and no entries were found then return error and close dirptr
1569 if (numentries == 0) {
1570 dptr_close(sconn, &dptr_num);
1571 } else if(expect_close && status_len == 0) {
1572 /* Close the dptr - we know it's gone */
1573 dptr_close(sconn, &dptr_num);
1576 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1577 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1578 dptr_close(sconn, &dptr_num);
1581 if ((numentries == 0) && !mask_contains_wcard) {
1582 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1586 SSVAL(req->outbuf,smb_vwv0,numentries);
1587 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1588 SCVAL(smb_buf(req->outbuf),0,5);
1589 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1591 /* The replies here are never long name. */
1592 SSVAL(req->outbuf, smb_flg2,
1593 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1594 if (!allow_long_path_components) {
1595 SSVAL(req->outbuf, smb_flg2,
1596 SVAL(req->outbuf, smb_flg2)
1597 & (~FLAGS2_LONG_PATH_COMPONENTS));
1600 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1601 SSVAL(req->outbuf, smb_flg2,
1602 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1604 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1605 smb_fn_name(req->cmd),
1612 TALLOC_FREE(directory);
1613 TALLOC_FREE(smb_fname);
1614 END_PROFILE(SMBsearch);
1618 /****************************************************************************
1619 Reply to a fclose (stop directory search).
1620 ****************************************************************************/
1622 void reply_fclose(struct smb_request *req)
1630 bool path_contains_wcard = False;
1631 TALLOC_CTX *ctx = talloc_tos();
1632 struct smbd_server_connection *sconn = smbd_server_conn;
1634 START_PROFILE(SMBfclose);
1636 if (lp_posix_pathnames()) {
1637 reply_unknown_new(req, req->cmd);
1638 END_PROFILE(SMBfclose);
1642 p = (const char *)req->buf + 1;
1643 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1644 &err, &path_contains_wcard);
1645 if (!NT_STATUS_IS_OK(err)) {
1646 reply_nterror(req, err);
1647 END_PROFILE(SMBfclose);
1651 status_len = SVAL(p,0);
1654 if (status_len == 0) {
1655 reply_doserror(req, ERRSRV, ERRsrverror);
1656 END_PROFILE(SMBfclose);
1660 memcpy(status,p,21);
1662 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1663 /* Close the dptr - we know it's gone */
1664 dptr_close(sconn, &dptr_num);
1667 reply_outbuf(req, 1, 0);
1668 SSVAL(req->outbuf,smb_vwv0,0);
1670 DEBUG(3,("search close\n"));
1672 END_PROFILE(SMBfclose);
1676 /****************************************************************************
1678 ****************************************************************************/
1680 void reply_open(struct smb_request *req)
1682 connection_struct *conn = req->conn;
1683 struct smb_filename *smb_fname = NULL;
1695 uint32 create_disposition;
1696 uint32 create_options = 0;
1698 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1699 TALLOC_CTX *ctx = talloc_tos();
1701 START_PROFILE(SMBopen);
1704 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1708 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1709 deny_mode = SVAL(req->vwv+0, 0);
1710 dos_attr = SVAL(req->vwv+1, 0);
1712 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1713 STR_TERMINATE, &status);
1714 if (!NT_STATUS_IS_OK(status)) {
1715 reply_nterror(req, status);
1719 status = filename_convert(ctx,
1721 req->flags2 & FLAGS2_DFS_PATHNAMES,
1726 if (!NT_STATUS_IS_OK(status)) {
1727 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1728 reply_botherror(req,
1729 NT_STATUS_PATH_NOT_COVERED,
1730 ERRSRV, ERRbadpath);
1733 reply_nterror(req, status);
1737 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1738 OPENX_FILE_EXISTS_OPEN, &access_mask,
1739 &share_mode, &create_disposition,
1741 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1745 status = SMB_VFS_CREATE_FILE(
1748 0, /* root_dir_fid */
1749 smb_fname, /* fname */
1750 access_mask, /* access_mask */
1751 share_mode, /* share_access */
1752 create_disposition, /* create_disposition*/
1753 create_options, /* create_options */
1754 dos_attr, /* file_attributes */
1755 oplock_request, /* oplock_request */
1756 0, /* allocation_size */
1762 if (!NT_STATUS_IS_OK(status)) {
1763 if (open_was_deferred(req->mid)) {
1764 /* We have re-scheduled this call. */
1767 reply_openerror(req, status);
1771 size = smb_fname->st.st_ex_size;
1772 fattr = dos_mode(conn, smb_fname);
1774 /* Deal with other possible opens having a modified
1776 if (ask_sharemode) {
1777 struct timespec write_time_ts;
1779 ZERO_STRUCT(write_time_ts);
1780 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1781 if (!null_timespec(write_time_ts)) {
1782 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1786 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1789 DEBUG(3,("attempt to open a directory %s\n",
1791 close_file(req, fsp, ERROR_CLOSE);
1792 reply_doserror(req, ERRDOS,ERRnoaccess);
1796 reply_outbuf(req, 7, 0);
1797 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1798 SSVAL(req->outbuf,smb_vwv1,fattr);
1799 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1800 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1802 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1804 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1805 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1807 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1808 SCVAL(req->outbuf,smb_flg,
1809 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1812 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1813 SCVAL(req->outbuf,smb_flg,
1814 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1817 TALLOC_FREE(smb_fname);
1818 END_PROFILE(SMBopen);
1822 /****************************************************************************
1823 Reply to an open and X.
1824 ****************************************************************************/
1826 void reply_open_and_X(struct smb_request *req)
1828 connection_struct *conn = req->conn;
1829 struct smb_filename *smb_fname = NULL;
1834 /* Breakout the oplock request bits so we can set the
1835 reply bits separately. */
1836 int ex_oplock_request;
1837 int core_oplock_request;
1840 int smb_sattr = SVAL(req->vwv+4, 0);
1841 uint32 smb_time = make_unix_date3(req->vwv+6);
1849 uint64_t allocation_size;
1850 ssize_t retval = -1;
1853 uint32 create_disposition;
1854 uint32 create_options = 0;
1855 TALLOC_CTX *ctx = talloc_tos();
1857 START_PROFILE(SMBopenX);
1859 if (req->wct < 15) {
1860 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1864 open_flags = SVAL(req->vwv+2, 0);
1865 deny_mode = SVAL(req->vwv+3, 0);
1866 smb_attr = SVAL(req->vwv+5, 0);
1867 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1868 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1869 oplock_request = ex_oplock_request | core_oplock_request;
1870 smb_ofun = SVAL(req->vwv+8, 0);
1871 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1873 /* If it's an IPC, pass off the pipe handler. */
1875 if (lp_nt_pipe_support()) {
1876 reply_open_pipe_and_X(conn, req);
1878 reply_doserror(req, ERRSRV, ERRaccess);
1883 /* XXXX we need to handle passed times, sattr and flags */
1884 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1885 STR_TERMINATE, &status);
1886 if (!NT_STATUS_IS_OK(status)) {
1887 reply_nterror(req, status);
1891 status = filename_convert(ctx,
1893 req->flags2 & FLAGS2_DFS_PATHNAMES,
1898 if (!NT_STATUS_IS_OK(status)) {
1899 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1900 reply_botherror(req,
1901 NT_STATUS_PATH_NOT_COVERED,
1902 ERRSRV, ERRbadpath);
1905 reply_nterror(req, status);
1909 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1910 &access_mask, &share_mode,
1911 &create_disposition,
1913 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1917 status = SMB_VFS_CREATE_FILE(
1920 0, /* root_dir_fid */
1921 smb_fname, /* fname */
1922 access_mask, /* access_mask */
1923 share_mode, /* share_access */
1924 create_disposition, /* create_disposition*/
1925 create_options, /* create_options */
1926 smb_attr, /* file_attributes */
1927 oplock_request, /* oplock_request */
1928 0, /* allocation_size */
1932 &smb_action); /* pinfo */
1934 if (!NT_STATUS_IS_OK(status)) {
1935 if (open_was_deferred(req->mid)) {
1936 /* We have re-scheduled this call. */
1939 reply_openerror(req, status);
1943 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1944 if the file is truncated or created. */
1945 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1946 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1947 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1948 close_file(req, fsp, ERROR_CLOSE);
1949 reply_nterror(req, NT_STATUS_DISK_FULL);
1952 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1954 close_file(req, fsp, ERROR_CLOSE);
1955 reply_nterror(req, NT_STATUS_DISK_FULL);
1958 smb_fname->st.st_ex_size =
1959 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1962 fattr = dos_mode(conn, smb_fname);
1963 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1965 close_file(req, fsp, ERROR_CLOSE);
1966 reply_doserror(req, ERRDOS, ERRnoaccess);
1970 /* If the caller set the extended oplock request bit
1971 and we granted one (by whatever means) - set the
1972 correct bit for extended oplock reply.
1975 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1976 smb_action |= EXTENDED_OPLOCK_GRANTED;
1979 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1980 smb_action |= EXTENDED_OPLOCK_GRANTED;
1983 /* If the caller set the core oplock request bit
1984 and we granted one (by whatever means) - set the
1985 correct bit for core oplock reply.
1988 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1989 reply_outbuf(req, 19, 0);
1991 reply_outbuf(req, 15, 0);
1994 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1995 SCVAL(req->outbuf, smb_flg,
1996 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1999 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2000 SCVAL(req->outbuf, smb_flg,
2001 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2004 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2005 SSVAL(req->outbuf,smb_vwv3,fattr);
2006 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2007 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2009 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2011 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2012 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2013 SSVAL(req->outbuf,smb_vwv11,smb_action);
2015 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2016 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2021 TALLOC_FREE(smb_fname);
2022 END_PROFILE(SMBopenX);
2026 /****************************************************************************
2027 Reply to a SMBulogoffX.
2028 ****************************************************************************/
2030 void reply_ulogoffX(struct smb_request *req)
2032 struct smbd_server_connection *sconn = smbd_server_conn;
2035 START_PROFILE(SMBulogoffX);
2037 vuser = get_valid_user_struct(sconn, req->vuid);
2040 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2044 /* in user level security we are supposed to close any files
2045 open by this user */
2046 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2047 file_close_user(req->vuid);
2050 invalidate_vuid(sconn, req->vuid);
2052 reply_outbuf(req, 2, 0);
2054 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2056 END_PROFILE(SMBulogoffX);
2057 req->vuid = UID_FIELD_INVALID;
2061 /****************************************************************************
2062 Reply to a mknew or a create.
2063 ****************************************************************************/
2065 void reply_mknew(struct smb_request *req)
2067 connection_struct *conn = req->conn;
2068 struct smb_filename *smb_fname = NULL;
2071 struct smb_file_time ft;
2073 int oplock_request = 0;
2075 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2076 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2077 uint32 create_disposition;
2078 uint32 create_options = 0;
2079 TALLOC_CTX *ctx = talloc_tos();
2081 START_PROFILE(SMBcreate);
2085 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2089 fattr = SVAL(req->vwv+0, 0);
2090 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2093 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2095 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2096 STR_TERMINATE, &status);
2097 if (!NT_STATUS_IS_OK(status)) {
2098 reply_nterror(req, status);
2102 status = filename_convert(ctx,
2104 req->flags2 & FLAGS2_DFS_PATHNAMES,
2109 if (!NT_STATUS_IS_OK(status)) {
2110 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2111 reply_botherror(req,
2112 NT_STATUS_PATH_NOT_COVERED,
2113 ERRSRV, ERRbadpath);
2116 reply_nterror(req, status);
2120 if (fattr & aVOLID) {
2121 DEBUG(0,("Attempt to create file (%s) with volid set - "
2122 "please report this\n",
2123 smb_fname_str_dbg(smb_fname)));
2126 if(req->cmd == SMBmknew) {
2127 /* We should fail if file exists. */
2128 create_disposition = FILE_CREATE;
2130 /* Create if file doesn't exist, truncate if it does. */
2131 create_disposition = FILE_OVERWRITE_IF;
2134 status = SMB_VFS_CREATE_FILE(
2137 0, /* root_dir_fid */
2138 smb_fname, /* fname */
2139 access_mask, /* access_mask */
2140 share_mode, /* share_access */
2141 create_disposition, /* create_disposition*/
2142 create_options, /* create_options */
2143 fattr, /* file_attributes */
2144 oplock_request, /* oplock_request */
2145 0, /* allocation_size */
2151 if (!NT_STATUS_IS_OK(status)) {
2152 if (open_was_deferred(req->mid)) {
2153 /* We have re-scheduled this call. */
2156 reply_openerror(req, status);
2160 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2161 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2162 if (!NT_STATUS_IS_OK(status)) {
2163 END_PROFILE(SMBcreate);
2167 reply_outbuf(req, 1, 0);
2168 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2170 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2171 SCVAL(req->outbuf,smb_flg,
2172 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2175 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2176 SCVAL(req->outbuf,smb_flg,
2177 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2180 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2181 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2182 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2183 (unsigned int)fattr));
2186 TALLOC_FREE(smb_fname);
2187 END_PROFILE(SMBcreate);
2191 /****************************************************************************
2192 Reply to a create temporary file.
2193 ****************************************************************************/
2195 void reply_ctemp(struct smb_request *req)
2197 connection_struct *conn = req->conn;
2198 struct smb_filename *smb_fname = NULL;
2206 TALLOC_CTX *ctx = talloc_tos();
2208 START_PROFILE(SMBctemp);
2211 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2215 fattr = SVAL(req->vwv+0, 0);
2216 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2218 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2219 STR_TERMINATE, &status);
2220 if (!NT_STATUS_IS_OK(status)) {
2221 reply_nterror(req, status);
2225 fname = talloc_asprintf(ctx,
2229 fname = talloc_strdup(ctx, "TMXXXXXX");
2233 reply_nterror(req, NT_STATUS_NO_MEMORY);
2237 status = filename_convert(ctx, conn,
2238 req->flags2 & FLAGS2_DFS_PATHNAMES,
2243 if (!NT_STATUS_IS_OK(status)) {
2244 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2245 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2246 ERRSRV, ERRbadpath);
2249 reply_nterror(req, status);
2253 tmpfd = mkstemp(smb_fname->base_name);
2255 reply_nterror(req, map_nt_error_from_unix(errno));
2259 SMB_VFS_STAT(conn, smb_fname);
2261 /* We should fail if file does not exist. */
2262 status = SMB_VFS_CREATE_FILE(
2265 0, /* root_dir_fid */
2266 smb_fname, /* fname */
2267 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2268 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2269 FILE_OPEN, /* create_disposition*/
2270 0, /* create_options */
2271 fattr, /* file_attributes */
2272 oplock_request, /* oplock_request */
2273 0, /* allocation_size */
2279 /* close fd from mkstemp() */
2282 if (!NT_STATUS_IS_OK(status)) {
2283 if (open_was_deferred(req->mid)) {
2284 /* We have re-scheduled this call. */
2287 reply_openerror(req, status);
2291 reply_outbuf(req, 1, 0);
2292 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2294 /* the returned filename is relative to the directory */
2295 s = strrchr_m(fsp->fsp_name->base_name, '/');
2297 s = fsp->fsp_name->base_name;
2303 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2304 thing in the byte section. JRA */
2305 SSVALS(p, 0, -1); /* what is this? not in spec */
2307 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2309 reply_nterror(req, NT_STATUS_NO_MEMORY);
2313 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2314 SCVAL(req->outbuf, smb_flg,
2315 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2318 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2319 SCVAL(req->outbuf, smb_flg,
2320 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2323 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2324 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2325 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2327 TALLOC_FREE(smb_fname);
2328 END_PROFILE(SMBctemp);
2332 /*******************************************************************
2333 Check if a user is allowed to rename a file.
2334 ********************************************************************/
2336 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2337 uint16 dirtype, SMB_STRUCT_STAT *pst)
2341 if (!CAN_WRITE(conn)) {
2342 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2345 fmode = dos_mode(conn, fsp->fsp_name);
2346 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2347 return NT_STATUS_NO_SUCH_FILE;
2350 if (S_ISDIR(pst->st_ex_mode)) {
2351 if (fsp->posix_open) {
2352 return NT_STATUS_OK;
2355 /* If no pathnames are open below this
2356 directory, allow the rename. */
2358 if (file_find_subpath(fsp)) {
2359 return NT_STATUS_ACCESS_DENIED;
2361 return NT_STATUS_OK;
2364 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2365 return NT_STATUS_OK;
2368 return NT_STATUS_ACCESS_DENIED;
2371 /*******************************************************************
2372 * unlink a file with all relevant access checks
2373 *******************************************************************/
2375 static NTSTATUS do_unlink(connection_struct *conn,
2376 struct smb_request *req,
2377 struct smb_filename *smb_fname,
2382 uint32 dirtype_orig = dirtype;
2385 bool posix_paths = lp_posix_pathnames();
2387 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2388 smb_fname_str_dbg(smb_fname),
2391 if (!CAN_WRITE(conn)) {
2392 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2396 ret = SMB_VFS_LSTAT(conn, smb_fname);
2398 ret = SMB_VFS_LSTAT(conn, smb_fname);
2401 return map_nt_error_from_unix(errno);
2404 fattr = dos_mode(conn, smb_fname);
2406 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2407 dirtype = aDIR|aARCH|aRONLY;
2410 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2412 return NT_STATUS_NO_SUCH_FILE;
2415 if (!dir_check_ftype(conn, fattr, dirtype)) {
2417 return NT_STATUS_FILE_IS_A_DIRECTORY;
2419 return NT_STATUS_NO_SUCH_FILE;
2422 if (dirtype_orig & 0x8000) {
2423 /* These will never be set for POSIX. */
2424 return NT_STATUS_NO_SUCH_FILE;
2428 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2429 return NT_STATUS_FILE_IS_A_DIRECTORY;
2432 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2433 return NT_STATUS_NO_SUCH_FILE;
2436 if (dirtype & 0xFF00) {
2437 /* These will never be set for POSIX. */
2438 return NT_STATUS_NO_SUCH_FILE;
2443 return NT_STATUS_NO_SUCH_FILE;
2446 /* Can't delete a directory. */
2448 return NT_STATUS_FILE_IS_A_DIRECTORY;
2453 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2454 return NT_STATUS_OBJECT_NAME_INVALID;
2455 #endif /* JRATEST */
2457 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2459 On a Windows share, a file with read-only dosmode can be opened with
2460 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2461 fails with NT_STATUS_CANNOT_DELETE error.
2463 This semantic causes a problem that a user can not
2464 rename a file with read-only dosmode on a Samba share
2465 from a Windows command prompt (i.e. cmd.exe, but can rename
2466 from Windows Explorer).
2469 if (!lp_delete_readonly(SNUM(conn))) {
2470 if (fattr & aRONLY) {
2471 return NT_STATUS_CANNOT_DELETE;
2475 /* On open checks the open itself will check the share mode, so
2476 don't do it here as we'll get it wrong. */
2478 status = SMB_VFS_CREATE_FILE
2481 0, /* root_dir_fid */
2482 smb_fname, /* fname */
2483 DELETE_ACCESS, /* access_mask */
2484 FILE_SHARE_NONE, /* share_access */
2485 FILE_OPEN, /* create_disposition*/
2486 FILE_NON_DIRECTORY_FILE, /* create_options */
2487 /* file_attributes */
2488 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2489 FILE_ATTRIBUTE_NORMAL,
2490 0, /* oplock_request */
2491 0, /* allocation_size */
2497 if (!NT_STATUS_IS_OK(status)) {
2498 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2499 nt_errstr(status)));
2503 /* The set is across all open files on this dev/inode pair. */
2504 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2505 close_file(req, fsp, NORMAL_CLOSE);
2506 return NT_STATUS_ACCESS_DENIED;
2509 return close_file(req, fsp, NORMAL_CLOSE);
2512 /****************************************************************************
2513 The guts of the unlink command, split out so it may be called by the NT SMB
2515 ****************************************************************************/
2517 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2518 uint32 dirtype, struct smb_filename *smb_fname,
2521 char *fname_dir = NULL;
2522 char *fname_mask = NULL;
2524 NTSTATUS status = NT_STATUS_OK;
2525 TALLOC_CTX *ctx = talloc_tos();
2527 /* Split up the directory from the filename/mask. */
2528 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2529 &fname_dir, &fname_mask);
2530 if (!NT_STATUS_IS_OK(status)) {
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) &&
2544 mangle_is_mangled(fname_mask, conn->params)) {
2545 char *new_mask = NULL;
2546 mangle_lookup_name_from_8_3(ctx, fname_mask,
2547 &new_mask, conn->params);
2549 TALLOC_FREE(fname_mask);
2550 fname_mask = new_mask;
2557 * Only one file needs to be unlinked. Append the mask back
2558 * onto the directory.
2560 TALLOC_FREE(smb_fname->base_name);
2561 smb_fname->base_name = talloc_asprintf(smb_fname,
2565 if (!smb_fname->base_name) {
2566 status = NT_STATUS_NO_MEMORY;
2570 dirtype = FILE_ATTRIBUTE_NORMAL;
2573 status = check_name(conn, smb_fname->base_name);
2574 if (!NT_STATUS_IS_OK(status)) {
2578 status = do_unlink(conn, req, smb_fname, dirtype);
2579 if (!NT_STATUS_IS_OK(status)) {
2585 struct smb_Dir *dir_hnd = NULL;
2589 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2590 status = NT_STATUS_OBJECT_NAME_INVALID;
2594 if (strequal(fname_mask,"????????.???")) {
2595 TALLOC_FREE(fname_mask);
2596 fname_mask = talloc_strdup(ctx, "*");
2598 status = NT_STATUS_NO_MEMORY;
2603 status = check_name(conn, fname_dir);
2604 if (!NT_STATUS_IS_OK(status)) {
2608 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2610 if (dir_hnd == NULL) {
2611 status = map_nt_error_from_unix(errno);
2615 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2616 the pattern matches against the long name, otherwise the short name
2617 We don't implement this yet XXXX
2620 status = NT_STATUS_NO_SUCH_FILE;
2622 while ((dname = ReadDirName(dir_hnd, &offset,
2624 TALLOC_CTX *frame = talloc_stackframe();
2626 if (!is_visible_file(conn, fname_dir, dname,
2627 &smb_fname->st, true)) {
2633 /* Quick check for "." and ".." */
2634 if (ISDOT(dname) || ISDOTDOT(dname)) {
2640 if(!mask_match(dname, fname_mask,
2641 conn->case_sensitive)) {
2647 TALLOC_FREE(smb_fname->base_name);
2648 smb_fname->base_name =
2649 talloc_asprintf(smb_fname, "%s/%s",
2652 if (!smb_fname->base_name) {
2653 TALLOC_FREE(dir_hnd);
2654 status = NT_STATUS_NO_MEMORY;
2660 status = check_name(conn, smb_fname->base_name);
2661 if (!NT_STATUS_IS_OK(status)) {
2662 TALLOC_FREE(dir_hnd);
2668 status = do_unlink(conn, req, smb_fname, dirtype);
2669 if (!NT_STATUS_IS_OK(status)) {
2676 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2677 smb_fname->base_name));
2682 TALLOC_FREE(dir_hnd);
2685 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2686 status = map_nt_error_from_unix(errno);
2690 TALLOC_FREE(fname_dir);
2691 TALLOC_FREE(fname_mask);
2695 /****************************************************************************
2697 ****************************************************************************/
2699 void reply_unlink(struct smb_request *req)
2701 connection_struct *conn = req->conn;
2703 struct smb_filename *smb_fname = NULL;
2706 bool path_contains_wcard = False;
2707 TALLOC_CTX *ctx = talloc_tos();
2709 START_PROFILE(SMBunlink);
2712 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2716 dirtype = SVAL(req->vwv+0, 0);
2718 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2719 STR_TERMINATE, &status,
2720 &path_contains_wcard);
2721 if (!NT_STATUS_IS_OK(status)) {
2722 reply_nterror(req, status);
2726 status = filename_convert(ctx, conn,
2727 req->flags2 & FLAGS2_DFS_PATHNAMES,
2729 UCF_COND_ALLOW_WCARD_LCOMP,
2730 &path_contains_wcard,
2732 if (!NT_STATUS_IS_OK(status)) {
2733 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2734 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2735 ERRSRV, ERRbadpath);
2738 reply_nterror(req, status);
2742 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2744 status = unlink_internals(conn, req, dirtype, smb_fname,
2745 path_contains_wcard);
2746 if (!NT_STATUS_IS_OK(status)) {
2747 if (open_was_deferred(req->mid)) {
2748 /* We have re-scheduled this call. */
2751 reply_nterror(req, status);
2755 reply_outbuf(req, 0, 0);
2757 TALLOC_FREE(smb_fname);
2758 END_PROFILE(SMBunlink);
2762 /****************************************************************************
2764 ****************************************************************************/
2766 static void fail_readraw(void)
2768 const char *errstr = talloc_asprintf(talloc_tos(),
2769 "FAIL ! reply_readbraw: socket write fail (%s)",
2774 exit_server_cleanly(errstr);
2777 /****************************************************************************
2778 Fake (read/write) sendfile. Returns -1 on read or write fail.
2779 ****************************************************************************/
2781 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2785 size_t tosend = nread;
2792 bufsize = MIN(nread, 65536);
2794 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2798 while (tosend > 0) {
2802 if (tosend > bufsize) {
2807 ret = read_file(fsp,buf,startpos,cur_read);
2813 /* If we had a short read, fill with zeros. */
2814 if (ret < cur_read) {
2815 memset(buf + ret, '\0', cur_read - ret);
2818 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2823 startpos += cur_read;
2827 return (ssize_t)nread;
2830 #if defined(WITH_SENDFILE)
2831 /****************************************************************************
2832 Deal with the case of sendfile reading less bytes from the file than
2833 requested. Fill with zeros (all we can do).
2834 ****************************************************************************/
2836 static void sendfile_short_send(files_struct *fsp,
2841 #define SHORT_SEND_BUFSIZE 1024
2842 if (nread < headersize) {
2843 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2844 "header for file %s (%s). Terminating\n",
2845 fsp_str_dbg(fsp), strerror(errno)));
2846 exit_server_cleanly("sendfile_short_send failed");
2849 nread -= headersize;
2851 if (nread < smb_maxcnt) {
2852 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2854 exit_server_cleanly("sendfile_short_send: "
2858 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2859 "with zeros !\n", fsp_str_dbg(fsp)));
2861 while (nread < smb_maxcnt) {
2863 * We asked for the real file size and told sendfile
2864 * to not go beyond the end of the file. But it can
2865 * happen that in between our fstat call and the
2866 * sendfile call the file was truncated. This is very
2867 * bad because we have already announced the larger
2868 * number of bytes to the client.
2870 * The best we can do now is to send 0-bytes, just as
2871 * a read from a hole in a sparse file would do.
2873 * This should happen rarely enough that I don't care
2874 * about efficiency here :-)
2878 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2879 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2880 exit_server_cleanly("sendfile_short_send: "
2881 "write_data failed");
2888 #endif /* defined WITH_SENDFILE */
2890 /****************************************************************************
2891 Return a readbraw error (4 bytes of zero).
2892 ****************************************************************************/
2894 static void reply_readbraw_error(void)
2898 if (write_data(smbd_server_fd(),header,4) != 4) {
2903 /****************************************************************************
2904 Use sendfile in readbraw.
2905 ****************************************************************************/
2907 static void send_file_readbraw(connection_struct *conn,
2908 struct smb_request *req,
2914 char *outbuf = NULL;
2917 #if defined(WITH_SENDFILE)
2919 * We can only use sendfile on a non-chained packet
2920 * but we can use on a non-oplocked file. tridge proved this
2921 * on a train in Germany :-). JRA.
2922 * reply_readbraw has already checked the length.
2925 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2926 (fsp->wcp == NULL) &&
2927 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2928 ssize_t sendfile_read = -1;
2930 DATA_BLOB header_blob;
2932 _smb_setlen(header,nread);
2933 header_blob = data_blob_const(header, 4);
2935 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2936 &header_blob, startpos, nread)) == -1) {
2937 /* Returning ENOSYS means no data at all was sent.
2938 * Do this as a normal read. */
2939 if (errno == ENOSYS) {
2940 goto normal_readbraw;
2944 * Special hack for broken Linux with no working sendfile. If we
2945 * return EINTR we sent the header but not the rest of the data.
2946 * Fake this up by doing read/write calls.
2948 if (errno == EINTR) {
2949 /* Ensure we don't do this again. */
2950 set_use_sendfile(SNUM(conn), False);
2951 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2953 if (fake_sendfile(fsp, startpos, nread) == -1) {
2954 DEBUG(0,("send_file_readbraw: "
2955 "fake_sendfile failed for "
2959 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2964 DEBUG(0,("send_file_readbraw: sendfile failed for "
2965 "file %s (%s). Terminating\n",
2966 fsp_str_dbg(fsp), strerror(errno)));
2967 exit_server_cleanly("send_file_readbraw sendfile failed");
2968 } else if (sendfile_read == 0) {
2970 * Some sendfile implementations return 0 to indicate
2971 * that there was a short read, but nothing was
2972 * actually written to the socket. In this case,
2973 * fallback to the normal read path so the header gets
2974 * the correct byte count.
2976 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2977 "bytes falling back to the normal read: "
2978 "%s\n", fsp_str_dbg(fsp)));
2979 goto normal_readbraw;
2982 /* Deal with possible short send. */
2983 if (sendfile_read != 4+nread) {
2984 sendfile_short_send(fsp, sendfile_read, 4, nread);
2992 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2994 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2995 (unsigned)(nread+4)));
2996 reply_readbraw_error();
3001 ret = read_file(fsp,outbuf+4,startpos,nread);
3002 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3011 _smb_setlen(outbuf,ret);
3012 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3015 TALLOC_FREE(outbuf);
3018 /****************************************************************************
3019 Reply to a readbraw (core+ protocol).
3020 ****************************************************************************/
3022 void reply_readbraw(struct smb_request *req)
3024 connection_struct *conn = req->conn;
3025 ssize_t maxcount,mincount;
3029 struct lock_struct lock;
3033 START_PROFILE(SMBreadbraw);
3035 if (srv_is_signing_active(smbd_server_conn) ||
3036 is_encrypted_packet(req->inbuf)) {
3037 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3038 "raw reads/writes are disallowed.");
3042 reply_readbraw_error();
3043 END_PROFILE(SMBreadbraw);
3048 * Special check if an oplock break has been issued
3049 * and the readraw request croses on the wire, we must
3050 * return a zero length response here.
3053 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3056 * We have to do a check_fsp by hand here, as
3057 * we must always return 4 zero bytes on error,
3061 if (!fsp || !conn || conn != fsp->conn ||
3062 req->vuid != fsp->vuid ||
3063 fsp->is_directory || fsp->fh->fd == -1) {
3065 * fsp could be NULL here so use the value from the packet. JRA.
3067 DEBUG(3,("reply_readbraw: fnum %d not valid "
3069 (int)SVAL(req->vwv+0, 0)));
3070 reply_readbraw_error();
3071 END_PROFILE(SMBreadbraw);
3075 /* Do a "by hand" version of CHECK_READ. */
3076 if (!(fsp->can_read ||
3077 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3078 (fsp->access_mask & FILE_EXECUTE)))) {
3079 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3080 (int)SVAL(req->vwv+0, 0)));
3081 reply_readbraw_error();
3082 END_PROFILE(SMBreadbraw);
3086 flush_write_cache(fsp, READRAW_FLUSH);
3088 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3089 if(req->wct == 10) {
3091 * This is a large offset (64 bit) read.
3093 #ifdef LARGE_SMB_OFF_T
3095 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3097 #else /* !LARGE_SMB_OFF_T */
3100 * Ensure we haven't been sent a >32 bit offset.
3103 if(IVAL(req->vwv+8, 0) != 0) {
3104 DEBUG(0,("reply_readbraw: large offset "
3105 "(%x << 32) used and we don't support "
3106 "64 bit offsets.\n",
3107 (unsigned int)IVAL(req->vwv+8, 0) ));
3108 reply_readbraw_error();
3109 END_PROFILE(SMBreadbraw);
3113 #endif /* LARGE_SMB_OFF_T */
3116 DEBUG(0,("reply_readbraw: negative 64 bit "
3117 "readraw offset (%.0f) !\n",
3118 (double)startpos ));
3119 reply_readbraw_error();
3120 END_PROFILE(SMBreadbraw);
3125 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3126 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3128 /* ensure we don't overrun the packet size */
3129 maxcount = MIN(65535,maxcount);
3131 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3132 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3135 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3136 reply_readbraw_error();
3137 END_PROFILE(SMBreadbraw);
3141 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3142 size = st.st_ex_size;
3145 if (startpos >= size) {
3148 nread = MIN(maxcount,(size - startpos));
3151 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3152 if (nread < mincount)
3156 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3157 "min=%lu nread=%lu\n",
3158 fsp->fnum, (double)startpos,
3159 (unsigned long)maxcount,
3160 (unsigned long)mincount,
3161 (unsigned long)nread ) );
3163 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3165 DEBUG(5,("reply_readbraw finished\n"));
3167 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3169 END_PROFILE(SMBreadbraw);
3174 #define DBGC_CLASS DBGC_LOCKING
3176 /****************************************************************************
3177 Reply to a lockread (core+ protocol).
3178 ****************************************************************************/
3180 void reply_lockread(struct smb_request *req)
3182 connection_struct *conn = req->conn;
3189 struct byte_range_lock *br_lck = NULL;
3191 struct smbd_server_connection *sconn = smbd_server_conn;
3193 START_PROFILE(SMBlockread);
3196 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3197 END_PROFILE(SMBlockread);
3201 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3203 if (!check_fsp(conn, req, fsp)) {
3204 END_PROFILE(SMBlockread);
3208 if (!CHECK_READ(fsp,req)) {
3209 reply_doserror(req, ERRDOS, ERRbadaccess);
3210 END_PROFILE(SMBlockread);
3214 numtoread = SVAL(req->vwv+1, 0);
3215 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3217 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3219 reply_outbuf(req, 5, numtoread + 3);
3221 data = smb_buf(req->outbuf) + 3;
3224 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3225 * protocol request that predates the read/write lock concept.
3226 * Thus instead of asking for a read lock here we need to ask
3227 * for a write lock. JRA.
3228 * Note that the requested lock size is unaffected by max_recv.
3231 br_lck = do_lock(smbd_messaging_context(),
3234 (uint64_t)numtoread,
3238 False, /* Non-blocking lock. */
3242 TALLOC_FREE(br_lck);
3244 if (NT_STATUS_V(status)) {
3245 reply_nterror(req, status);
3246 END_PROFILE(SMBlockread);
3251 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3254 if (numtoread > sconn->smb1.negprot.max_recv) {
3255 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3256 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3257 (unsigned int)numtoread,
3258 (unsigned int)sconn->smb1.negprot.max_recv));
3259 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3261 nread = read_file(fsp,data,startpos,numtoread);
3264 reply_nterror(req, map_nt_error_from_unix(errno));
3265 END_PROFILE(SMBlockread);
3269 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3271 SSVAL(req->outbuf,smb_vwv0,nread);
3272 SSVAL(req->outbuf,smb_vwv5,nread+3);
3273 p = smb_buf(req->outbuf);
3274 SCVAL(p,0,0); /* pad byte. */
3277 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3278 fsp->fnum, (int)numtoread, (int)nread));
3280 END_PROFILE(SMBlockread);
3285 #define DBGC_CLASS DBGC_ALL
3287 /****************************************************************************
3289 ****************************************************************************/
3291 void reply_read(struct smb_request *req)
3293 connection_struct *conn = req->conn;
3300 struct lock_struct lock;
3301 struct smbd_server_connection *sconn = smbd_server_conn;
3303 START_PROFILE(SMBread);
3306 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3307 END_PROFILE(SMBread);
3311 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3313 if (!check_fsp(conn, req, fsp)) {
3314 END_PROFILE(SMBread);
3318 if (!CHECK_READ(fsp,req)) {
3319 reply_doserror(req, ERRDOS, ERRbadaccess);
3320 END_PROFILE(SMBread);
3324 numtoread = SVAL(req->vwv+1, 0);
3325 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3327 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3330 * The requested read size cannot be greater than max_recv. JRA.
3332 if (numtoread > sconn->smb1.negprot.max_recv) {
3333 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3334 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3335 (unsigned int)numtoread,
3336 (unsigned int)sconn->smb1.negprot.max_recv));
3337 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3340 reply_outbuf(req, 5, numtoread+3);
3342 data = smb_buf(req->outbuf) + 3;
3344 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3345 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3348 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3349 reply_doserror(req, ERRDOS,ERRlock);
3350 END_PROFILE(SMBread);
3355 nread = read_file(fsp,data,startpos,numtoread);
3358 reply_nterror(req, map_nt_error_from_unix(errno));
3362 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3364 SSVAL(req->outbuf,smb_vwv0,nread);
3365 SSVAL(req->outbuf,smb_vwv5,nread+3);
3366 SCVAL(smb_buf(req->outbuf),0,1);
3367 SSVAL(smb_buf(req->outbuf),1,nread);
3369 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3370 fsp->fnum, (int)numtoread, (int)nread ) );
3373 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3375 END_PROFILE(SMBread);
3379 /****************************************************************************
3381 ****************************************************************************/
3383 static int setup_readX_header(struct smb_request *req, char *outbuf,
3389 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3390 data = smb_buf(outbuf);
3392 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3394 SCVAL(outbuf,smb_vwv0,0xFF);
3395 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3396 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3397 SSVAL(outbuf,smb_vwv6,
3399 + 1 /* the wct field */
3400 + 12 * sizeof(uint16_t) /* vwv */
3401 + 2); /* the buflen field */
3402 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3403 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3404 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3405 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3409 /****************************************************************************
3410 Reply to a read and X - possibly using sendfile.
3411 ****************************************************************************/
3413 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3414 files_struct *fsp, SMB_OFF_T startpos,
3417 SMB_STRUCT_STAT sbuf;
3419 struct lock_struct lock;
3420 int saved_errno = 0;
3422 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3423 reply_nterror(req, map_nt_error_from_unix(errno));
3427 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3428 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3431 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3432 reply_doserror(req, ERRDOS, ERRlock);
3436 if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
3437 || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
3439 * We already know that we would do a short read, so don't
3440 * try the sendfile() path.
3442 goto nosendfile_read;
3445 #if defined(WITH_SENDFILE)
3447 * We can only use sendfile on a non-chained packet
3448 * but we can use on a non-oplocked file. tridge proved this
3449 * on a train in Germany :-). JRA.
3452 if (!req_is_in_chain(req) &&
3453 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3454 (fsp->wcp == NULL) &&
3455 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3456 uint8 headerbuf[smb_size + 12 * 2];
3460 * Set up the packet header before send. We
3461 * assume here the sendfile will work (get the
3462 * correct amount of data).
3465 header = data_blob_const(headerbuf, sizeof(headerbuf));
3467 construct_reply_common_req(req, (char *)headerbuf);
3468 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3470 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3471 /* Returning ENOSYS means no data at all was sent.
3472 Do this as a normal read. */
3473 if (errno == ENOSYS) {
3478 * Special hack for broken Linux with no working sendfile. If we
3479 * return EINTR we sent the header but not the rest of the data.
3480 * Fake this up by doing read/write calls.
3483 if (errno == EINTR) {
3484 /* Ensure we don't do this again. */
3485 set_use_sendfile(SNUM(conn), False);
3486 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3487 nread = fake_sendfile(fsp, startpos,
3490 DEBUG(0,("send_file_readX: "
3491 "fake_sendfile failed for "
3495 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3497 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3498 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3499 /* No outbuf here means successful sendfile. */
3503 DEBUG(0,("send_file_readX: sendfile failed for file "
3504 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3506 exit_server_cleanly("send_file_readX sendfile failed");
3507 } else if (nread == 0) {
3509 * Some sendfile implementations return 0 to indicate
3510 * that there was a short read, but nothing was
3511 * actually written to the socket. In this case,
3512 * fallback to the normal read path so the header gets
3513 * the correct byte count.
3515 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3516 "falling back to the normal read: %s\n",
3521 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3522 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3524 /* Deal with possible short send. */
3525 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3526 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3528 /* No outbuf here means successful sendfile. */
3529 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3530 SMB_PERFCOUNT_END(&req->pcd);
3538 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3539 uint8 headerbuf[smb_size + 2*12];
3541 construct_reply_common_req(req, (char *)headerbuf);
3542 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3544 /* Send out the header. */
3545 if (write_data(smbd_server_fd(), (char *)headerbuf,
3546 sizeof(headerbuf)) != sizeof(headerbuf)) {
3547 DEBUG(0,("send_file_readX: write_data failed for file "
3548 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3550 exit_server_cleanly("send_file_readX sendfile failed");
3552 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3554 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3555 "file %s (%s).\n", fsp_str_dbg(fsp),
3557 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3564 reply_outbuf(req, 12, smb_maxcnt);
3566 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3567 saved_errno = errno;
3569 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3572 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3576 setup_readX_header(req, (char *)req->outbuf, nread);
3578 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3579 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3585 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3586 TALLOC_FREE(req->outbuf);
3590 /****************************************************************************
3591 Reply to a read and X.
3592 ****************************************************************************/
3594 void reply_read_and_X(struct smb_request *req)
3596 connection_struct *conn = req->conn;
3600 bool big_readX = False;
3602 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3605 START_PROFILE(SMBreadX);
3607 if ((req->wct != 10) && (req->wct != 12)) {
3608 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3612 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3613 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3614 smb_maxcnt = SVAL(req->vwv+5, 0);
3616 /* If it's an IPC, pass off the pipe handler. */
3618 reply_pipe_read_and_X(req);
3619 END_PROFILE(SMBreadX);
3623 if (!check_fsp(conn, req, fsp)) {
3624 END_PROFILE(SMBreadX);
3628 if (!CHECK_READ(fsp,req)) {
3629 reply_doserror(req, ERRDOS,ERRbadaccess);
3630 END_PROFILE(SMBreadX);
3634 if (global_client_caps & CAP_LARGE_READX) {
3635 size_t upper_size = SVAL(req->vwv+7, 0);
3636 smb_maxcnt |= (upper_size<<16);
3637 if (upper_size > 1) {
3638 /* Can't do this on a chained packet. */
3639 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3640 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3641 END_PROFILE(SMBreadX);
3644 /* We currently don't do this on signed or sealed data. */
3645 if (srv_is_signing_active(smbd_server_conn) ||
3646 is_encrypted_packet(req->inbuf)) {
3647 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3648 END_PROFILE(SMBreadX);
3651 /* Is there room in the reply for this data ? */
3652 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3654 NT_STATUS_INVALID_PARAMETER);
3655 END_PROFILE(SMBreadX);
3662 if (req->wct == 12) {
3663 #ifdef LARGE_SMB_OFF_T
3665 * This is a large offset (64 bit) read.
3667 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3669 #else /* !LARGE_SMB_OFF_T */
3672 * Ensure we haven't been sent a >32 bit offset.
3675 if(IVAL(req->vwv+10, 0) != 0) {
3676 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3677 "used and we don't support 64 bit offsets.\n",
3678 (unsigned int)IVAL(req->vwv+10, 0) ));
3679 END_PROFILE(SMBreadX);
3680 reply_doserror(req, ERRDOS, ERRbadaccess);
3684 #endif /* LARGE_SMB_OFF_T */
3689 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3693 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3696 END_PROFILE(SMBreadX);
3700 /****************************************************************************
3701 Error replies to writebraw must have smb_wct == 1. Fix this up.
3702 ****************************************************************************/
3704 void error_to_writebrawerr(struct smb_request *req)
3706 uint8 *old_outbuf = req->outbuf;
3708 reply_outbuf(req, 1, 0);
3710 memcpy(req->outbuf, old_outbuf, smb_size);
3711 TALLOC_FREE(old_outbuf);
3714 /****************************************************************************
3715 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3716 ****************************************************************************/
3718 void reply_writebraw(struct smb_request *req)
3720 connection_struct *conn = req->conn;
3723 ssize_t total_written=0;
3724 size_t numtowrite=0;
3730 struct lock_struct lock;
3733 START_PROFILE(SMBwritebraw);
3736 * If we ever reply with an error, it must have the SMB command
3737 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3740 SCVAL(req->inbuf,smb_com,SMBwritec);
3742 if (srv_is_signing_active(smbd_server_conn)) {
3743 END_PROFILE(SMBwritebraw);
3744 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3745 "raw reads/writes are disallowed.");
3748 if (req->wct < 12) {
3749 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3750 error_to_writebrawerr(req);
3751 END_PROFILE(SMBwritebraw);
3755 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3756 if (!check_fsp(conn, req, fsp)) {
3757 error_to_writebrawerr(req);
3758 END_PROFILE(SMBwritebraw);
3762 if (!CHECK_WRITE(fsp)) {
3763 reply_doserror(req, ERRDOS, ERRbadaccess);
3764 error_to_writebrawerr(req);
3765 END_PROFILE(SMBwritebraw);
3769 tcount = IVAL(req->vwv+1, 0);
3770 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3771 write_through = BITSETW(req->vwv+7,0);
3773 /* We have to deal with slightly different formats depending
3774 on whether we are using the core+ or lanman1.0 protocol */
3776 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3777 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3778 data = smb_buf(req->inbuf);
3780 numtowrite = SVAL(req->vwv+10, 0);
3781 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3784 /* Ensure we don't write bytes past the end of this packet. */
3785 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3786 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3787 error_to_writebrawerr(req);
3788 END_PROFILE(SMBwritebraw);
3792 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3793 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3796 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3797 reply_doserror(req, ERRDOS, ERRlock);
3798 error_to_writebrawerr(req);
3799 END_PROFILE(SMBwritebraw);
3804 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3807 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3808 "wrote=%d sync=%d\n",
3809 fsp->fnum, (double)startpos, (int)numtowrite,
3810 (int)nwritten, (int)write_through));
3812 if (nwritten < (ssize_t)numtowrite) {
3813 reply_doserror(req, ERRHRD, ERRdiskfull);
3814 error_to_writebrawerr(req);
3818 total_written = nwritten;
3820 /* Allocate a buffer of 64k + length. */
3821 buf = TALLOC_ARRAY(NULL, char, 65540);
3823 reply_doserror(req, ERRDOS, ERRnomem);
3824 error_to_writebrawerr(req);
3828 /* Return a SMBwritebraw message to the redirector to tell
3829 * it to send more bytes */
3831 memcpy(buf, req->inbuf, smb_size);
3832 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3833 SCVAL(buf,smb_com,SMBwritebraw);
3834 SSVALS(buf,smb_vwv0,0xFFFF);
3836 if (!srv_send_smb(smbd_server_fd(),
3838 false, 0, /* no signing */
3839 IS_CONN_ENCRYPTED(conn),
3841 exit_server_cleanly("reply_writebraw: srv_send_smb "
3845 /* Now read the raw data into the buffer and write it */
3846 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3848 if (!NT_STATUS_IS_OK(status)) {
3849 exit_server_cleanly("secondary writebraw failed");
3852 /* Set up outbuf to return the correct size */
3853 reply_outbuf(req, 1, 0);
3855 if (numtowrite != 0) {
3857 if (numtowrite > 0xFFFF) {
3858 DEBUG(0,("reply_writebraw: Oversize secondary write "
3859 "raw requested (%u). Terminating\n",
3860 (unsigned int)numtowrite ));
3861 exit_server_cleanly("secondary writebraw failed");
3864 if (tcount > nwritten+numtowrite) {
3865 DEBUG(3,("reply_writebraw: Client overestimated the "
3867 (int)tcount,(int)nwritten,(int)numtowrite));
3870 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3872 if (!NT_STATUS_IS_OK(status)) {
3873 DEBUG(0,("reply_writebraw: Oversize secondary write "
3874 "raw read failed (%s). Terminating\n",
3875 nt_errstr(status)));
3876 exit_server_cleanly("secondary writebraw failed");
3879 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3880 if (nwritten == -1) {
3882 reply_nterror(req, map_nt_error_from_unix(errno));
3883 error_to_writebrawerr(req);
3887 if (nwritten < (ssize_t)numtowrite) {
3888 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3889 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3893 total_written += nwritten;
3898 SSVAL(req->outbuf,smb_vwv0,total_written);
3900 status = sync_file(conn, fsp, write_through);
3901 if (!NT_STATUS_IS_OK(status)) {
3902 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3903 fsp_str_dbg(fsp), nt_errstr(status)));
3904 reply_nterror(req, status);
3905 error_to_writebrawerr(req);
3909 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3911 fsp->fnum, (double)startpos, (int)numtowrite,
3912 (int)total_written));
3914 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3916 /* We won't return a status if write through is not selected - this
3917 * follows what WfWg does */
3918 END_PROFILE(SMBwritebraw);
3920 if (!write_through && total_written==tcount) {
3922 #if RABBIT_PELLET_FIX
3924 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3925 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3928 if (!send_keepalive(smbd_server_fd())) {
3929 exit_server_cleanly("reply_writebraw: send of "
3930 "keepalive failed");
3933 TALLOC_FREE(req->outbuf);
3938 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3940 END_PROFILE(SMBwritebraw);
3945 #define DBGC_CLASS DBGC_LOCKING
3947 /****************************************************************************
3948 Reply to a writeunlock (core+).
3949 ****************************************************************************/
3951 void reply_writeunlock(struct smb_request *req)
3953 connection_struct *conn = req->conn;
3954 ssize_t nwritten = -1;
3958 NTSTATUS status = NT_STATUS_OK;
3960 struct lock_struct lock;
3961 int saved_errno = 0;
3963 START_PROFILE(SMBwriteunlock);
3966 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3967 END_PROFILE(SMBwriteunlock);
3971 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3973 if (!check_fsp(conn, req, fsp)) {
3974 END_PROFILE(SMBwriteunlock);
3978 if (!CHECK_WRITE(fsp)) {
3979 reply_doserror(req, ERRDOS,ERRbadaccess);
3980 END_PROFILE(SMBwriteunlock);
3984 numtowrite = SVAL(req->vwv+1, 0);
3985 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3986 data = (const char *)req->buf + 3;
3989 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3990 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3993 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3994 reply_doserror(req, ERRDOS, ERRlock);
3995 END_PROFILE(SMBwriteunlock);
4000 /* The special X/Open SMB protocol handling of
4001 zero length writes is *NOT* done for
4003 if(numtowrite == 0) {
4006 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4007 saved_errno = errno;
4010 status = sync_file(conn, fsp, False /* write through */);
4011 if (!NT_STATUS_IS_OK(status)) {
4012 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4013 fsp_str_dbg(fsp), nt_errstr(status)));
4014 reply_nterror(req, status);
4019 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4023 if((nwritten < numtowrite) && (numtowrite != 0)) {
4024 reply_doserror(req, ERRHRD, ERRdiskfull);
4029 status = do_unlock(smbd_messaging_context(),
4032 (uint64_t)numtowrite,
4036 if (NT_STATUS_V(status)) {
4037 reply_nterror(req, status);
4042 reply_outbuf(req, 1, 0);
4044 SSVAL(req->outbuf,smb_vwv0,nwritten);
4046 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4047 fsp->fnum, (int)numtowrite, (int)nwritten));
4051 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4054 END_PROFILE(SMBwriteunlock);
4059 #define DBGC_CLASS DBGC_ALL
4061 /****************************************************************************
4063 ****************************************************************************/
4065 void reply_write(struct smb_request *req)
4067 connection_struct *conn = req->conn;
4069 ssize_t nwritten = -1;
4073 struct lock_struct lock;
4075 int saved_errno = 0;
4077 START_PROFILE(SMBwrite);
4080 END_PROFILE(SMBwrite);
4081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4085 /* If it's an IPC, pass off the pipe handler. */
4087 reply_pipe_write(req);
4088 END_PROFILE(SMBwrite);
4092 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4094 if (!check_fsp(conn, req, fsp)) {
4095 END_PROFILE(SMBwrite);
4099 if (!CHECK_WRITE(fsp)) {
4100 reply_doserror(req, ERRDOS, ERRbadaccess);
4101 END_PROFILE(SMBwrite);
4105 numtowrite = SVAL(req->vwv+1, 0);
4106 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4107 data = (const char *)req->buf + 3;
4109 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4110 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4113 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4114 reply_doserror(req, ERRDOS, ERRlock);
4115 END_PROFILE(SMBwrite);
4120 * X/Open SMB protocol says that if smb_vwv1 is
4121 * zero then the file size should be extended or
4122 * truncated to the size given in smb_vwv[2-3].
4125 if(numtowrite == 0) {
4127 * This is actually an allocate call, and set EOF. JRA.
4129 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4131 reply_nterror(req, NT_STATUS_DISK_FULL);
4134 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4136 reply_nterror(req, NT_STATUS_DISK_FULL);
4139 trigger_write_time_update_immediate(fsp);
4141 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4144 status = sync_file(conn, fsp, False);
4145 if (!NT_STATUS_IS_OK(status)) {
4146 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4147 fsp_str_dbg(fsp), nt_errstr(status)));
4148 reply_nterror(req, status);
4153 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4157 if((nwritten == 0) && (numtowrite != 0)) {
4158 reply_doserror(req, ERRHRD, ERRdiskfull);
4162 reply_outbuf(req, 1, 0);
4164 SSVAL(req->outbuf,smb_vwv0,nwritten);
4166 if (nwritten < (ssize_t)numtowrite) {
4167 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4168 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4171 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4174 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4176 END_PROFILE(SMBwrite);
4180 /****************************************************************************
4181 Ensure a buffer is a valid writeX for recvfile purposes.
4182 ****************************************************************************/
4184 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4185 (2*14) + /* word count (including bcc) */ \
4188 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4191 connection_struct *conn = NULL;
4192 unsigned int doff = 0;
4193 size_t len = smb_len_large(inbuf);
4194 struct smbd_server_connection *sconn = smbd_server_conn;
4196 if (is_encrypted_packet(inbuf)) {
4197 /* Can't do this on encrypted
4202 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4206 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4207 CVAL(inbuf,smb_wct) != 14) {
4208 DEBUG(10,("is_valid_writeX_buffer: chained or "
4209 "invalid word length.\n"));
4213 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4215 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4219 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4222 if (IS_PRINT(conn)) {
4223 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4226 doff = SVAL(inbuf,smb_vwv11);
4228 numtowrite = SVAL(inbuf,smb_vwv10);
4230 if (len > doff && len - doff > 0xFFFF) {
4231 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4234 if (numtowrite == 0) {
4235 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4239 /* Ensure the sizes match up. */
4240 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4241 /* no pad byte...old smbclient :-( */
4242 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4244 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4248 if (len - doff != numtowrite) {
4249 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4250 "len = %u, doff = %u, numtowrite = %u\n",
4253 (unsigned int)numtowrite ));
4257 DEBUG(10,("is_valid_writeX_buffer: true "
4258 "len = %u, doff = %u, numtowrite = %u\n",
4261 (unsigned int)numtowrite ));
4266 /****************************************************************************
4267 Reply to a write and X.
4268 ****************************************************************************/
4270 void reply_write_and_X(struct smb_request *req)
4272 connection_struct *conn = req->conn;
4274 struct lock_struct lock;
4279 unsigned int smb_doff;
4280 unsigned int smblen;
4284 START_PROFILE(SMBwriteX);
4286 if ((req->wct != 12) && (req->wct != 14)) {
4287 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4288 END_PROFILE(SMBwriteX);
4292 numtowrite = SVAL(req->vwv+10, 0);
4293 smb_doff = SVAL(req->vwv+11, 0);
4294 smblen = smb_len(req->inbuf);
4296 if (req->unread_bytes > 0xFFFF ||
4297 (smblen > smb_doff &&
4298 smblen - smb_doff > 0xFFFF)) {
4299 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4302 if (req->unread_bytes) {
4303 /* Can't do a recvfile write on IPC$ */
4305 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4306 END_PROFILE(SMBwriteX);
4309 if (numtowrite != req->unread_bytes) {
4310 reply_doserror(req, ERRDOS, ERRbadmem);
4311 END_PROFILE(SMBwriteX);
4315 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4316 smb_doff + numtowrite > smblen) {
4317 reply_doserror(req, ERRDOS, ERRbadmem);
4318 END_PROFILE(SMBwriteX);
4323 /* If it's an IPC, pass off the pipe handler. */
4325 if (req->unread_bytes) {
4326 reply_doserror(req, ERRDOS, ERRbadmem);
4327 END_PROFILE(SMBwriteX);
4330 reply_pipe_write_and_X(req);
4331 END_PROFILE(SMBwriteX);
4335 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4336 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4337 write_through = BITSETW(req->vwv+7,0);
4339 if (!check_fsp(conn, req, fsp)) {
4340 END_PROFILE(SMBwriteX);
4344 if (!CHECK_WRITE(fsp)) {
4345 reply_doserror(req, ERRDOS, ERRbadaccess);
4346 END_PROFILE(SMBwriteX);
4350 data = smb_base(req->inbuf) + smb_doff;
4352 if(req->wct == 14) {
4353 #ifdef LARGE_SMB_OFF_T
4355 * This is a large offset (64 bit) write.
4357 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4359 #else /* !LARGE_SMB_OFF_T */
4362 * Ensure we haven't been sent a >32 bit offset.
4365 if(IVAL(req->vwv+12, 0) != 0) {
4366 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4367 "used and we don't support 64 bit offsets.\n",
4368 (unsigned int)IVAL(req->vwv+12, 0) ));
4369 reply_doserror(req, ERRDOS, ERRbadaccess);
4370 END_PROFILE(SMBwriteX);
4374 #endif /* LARGE_SMB_OFF_T */
4377 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4378 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4381 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4382 reply_doserror(req, ERRDOS, ERRlock);
4383 END_PROFILE(SMBwriteX);
4387 /* X/Open SMB protocol says that, unlike SMBwrite
4388 if the length is zero then NO truncation is
4389 done, just a write of zero. To truncate a file,
4392 if(numtowrite == 0) {
4396 if ((req->unread_bytes == 0) &&
4397 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4402 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4406 reply_nterror(req, map_nt_error_from_unix(errno));
4410 if((nwritten == 0) && (numtowrite != 0)) {
4411 reply_doserror(req, ERRHRD, ERRdiskfull);
4415 reply_outbuf(req, 6, 0);
4416 SSVAL(req->outbuf,smb_vwv2,nwritten);
4417 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4419 if (nwritten < (ssize_t)numtowrite) {
4420 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4421 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4424 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4425 fsp->fnum, (int)numtowrite, (int)nwritten));
4427 status = sync_file(conn, fsp, write_through);
4428 if (!NT_STATUS_IS_OK(status)) {
4429 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4430 fsp_str_dbg(fsp), nt_errstr(status)));
4431 reply_nterror(req, status);
4435 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4437 END_PROFILE(SMBwriteX);
4442 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4444 END_PROFILE(SMBwriteX);
4448 /****************************************************************************
4450 ****************************************************************************/
4452 void reply_lseek(struct smb_request *req)
4454 connection_struct *conn = req->conn;
4460 START_PROFILE(SMBlseek);
4463 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4464 END_PROFILE(SMBlseek);
4468 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4470 if (!check_fsp(conn, req, fsp)) {
4474 flush_write_cache(fsp, SEEK_FLUSH);
4476 mode = SVAL(req->vwv+1, 0) & 3;
4477 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4478 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4487 res = fsp->fh->pos + startpos;
4498 if (umode == SEEK_END) {
4499 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4500 if(errno == EINVAL) {
4501 SMB_OFF_T current_pos = startpos;
4502 SMB_STRUCT_STAT sbuf;
4504 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4506 map_nt_error_from_unix(errno));
4507 END_PROFILE(SMBlseek);
4511 current_pos += sbuf.st_ex_size;
4513 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4518 reply_nterror(req, map_nt_error_from_unix(errno));
4519 END_PROFILE(SMBlseek);
4526 reply_outbuf(req, 2, 0);
4527 SIVAL(req->outbuf,smb_vwv0,res);
4529 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4530 fsp->fnum, (double)startpos, (double)res, mode));
4532 END_PROFILE(SMBlseek);
4536 /****************************************************************************
4538 ****************************************************************************/
4540 void reply_flush(struct smb_request *req)
4542 connection_struct *conn = req->conn;
4546 START_PROFILE(SMBflush);
4549 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4553 fnum = SVAL(req->vwv+0, 0);
4554 fsp = file_fsp(req, fnum);
4556 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4561 file_sync_all(conn);
4563 NTSTATUS status = sync_file(conn, fsp, True);
4564 if (!NT_STATUS_IS_OK(status)) {
4565 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4566 fsp_str_dbg(fsp), nt_errstr(status)));
4567 reply_nterror(req, status);
4568 END_PROFILE(SMBflush);
4573 reply_outbuf(req, 0, 0);
4575 DEBUG(3,("flush\n"));
4576 END_PROFILE(SMBflush);
4580 /****************************************************************************
4582 conn POINTER CAN BE NULL HERE !
4583 ****************************************************************************/
4585 void reply_exit(struct smb_request *req)
4587 START_PROFILE(SMBexit);
4589 file_close_pid(req->smbpid, req->vuid);
4591 reply_outbuf(req, 0, 0);
4593 DEBUG(3,("exit\n"));
4595 END_PROFILE(SMBexit);
4599 /****************************************************************************
4600 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4601 ****************************************************************************/
4603 void reply_close(struct smb_request *req)
4605 connection_struct *conn = req->conn;
4606 NTSTATUS status = NT_STATUS_OK;
4607 files_struct *fsp = NULL;
4608 START_PROFILE(SMBclose);
4611 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4612 END_PROFILE(SMBclose);
4616 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4619 * We can only use check_fsp if we know it's not a directory.
4622 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4623 reply_doserror(req, ERRDOS, ERRbadfid);
4624 END_PROFILE(SMBclose);
4628 if(fsp->is_directory) {
4630 * Special case - close NT SMB directory handle.
4632 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4633 status = close_file(req, fsp, NORMAL_CLOSE);
4637 * Close ordinary file.
4640 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4641 fsp->fh->fd, fsp->fnum,
4642 conn->num_files_open));
4645 * Take care of any time sent in the close.
4648 t = srv_make_unix_date3(req->vwv+1);
4649 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4652 * close_file() returns the unix errno if an error
4653 * was detected on close - normally this is due to
4654 * a disk full error. If not then it was probably an I/O error.
4657 status = close_file(req, fsp, NORMAL_CLOSE);
4660 if (!NT_STATUS_IS_OK(status)) {
4661 reply_nterror(req, status);
4662 END_PROFILE(SMBclose);
4666 reply_outbuf(req, 0, 0);
4667 END_PROFILE(SMBclose);
4671 /****************************************************************************
4672 Reply to a writeclose (Core+ protocol).
4673 ****************************************************************************/
4675 void reply_writeclose(struct smb_request *req)
4677 connection_struct *conn = req->conn;
4679 ssize_t nwritten = -1;
4680 NTSTATUS close_status = NT_STATUS_OK;
4683 struct timespec mtime;
4685 struct lock_struct lock;
4687 START_PROFILE(SMBwriteclose);
4690 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4691 END_PROFILE(SMBwriteclose);
4695 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4697 if (!check_fsp(conn, req, fsp)) {
4698 END_PROFILE(SMBwriteclose);
4701 if (!CHECK_WRITE(fsp)) {
4702 reply_doserror(req, ERRDOS,ERRbadaccess);
4703 END_PROFILE(SMBwriteclose);
4707 numtowrite = SVAL(req->vwv+1, 0);
4708 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4709 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4710 data = (const char *)req->buf + 1;
4713 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4714 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4717 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4718 reply_doserror(req, ERRDOS,ERRlock);
4719 END_PROFILE(SMBwriteclose);
4724 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4726 set_close_write_time(fsp, mtime);
4729 * More insanity. W2K only closes the file if writelen > 0.
4734 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4735 "file %s\n", fsp_str_dbg(fsp)));
4736 close_status = close_file(req, fsp, NORMAL_CLOSE);
4739 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4740 fsp->fnum, (int)numtowrite, (int)nwritten,
4741 conn->num_files_open));
4743 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4744 reply_doserror(req, ERRHRD, ERRdiskfull);
4748 if(!NT_STATUS_IS_OK(close_status)) {
4749 reply_nterror(req, close_status);
4753 reply_outbuf(req, 1, 0);
4755 SSVAL(req->outbuf,smb_vwv0,nwritten);
4759 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4762 END_PROFILE(SMBwriteclose);
4767 #define DBGC_CLASS DBGC_LOCKING
4769 /****************************************************************************
4771 ****************************************************************************/
4773 void reply_lock(struct smb_request *req)
4775 connection_struct *conn = req->conn;
4776 uint64_t count,offset;
4779 struct byte_range_lock *br_lck = NULL;
4781 START_PROFILE(SMBlock);
4784 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4785 END_PROFILE(SMBlock);
4789 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4791 if (!check_fsp(conn, req, fsp)) {
4792 END_PROFILE(SMBlock);
4796 count = (uint64_t)IVAL(req->vwv+1, 0);
4797 offset = (uint64_t)IVAL(req->vwv+3, 0);
4799 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4800 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4802 br_lck = do_lock(smbd_messaging_context(),
4809 False, /* Non-blocking lock. */
4814 TALLOC_FREE(br_lck);
4816 if (NT_STATUS_V(status)) {
4817 reply_nterror(req, status);
4818 END_PROFILE(SMBlock);
4822 reply_outbuf(req, 0, 0);
4824 END_PROFILE(SMBlock);
4828 /****************************************************************************
4830 ****************************************************************************/
4832 void reply_unlock(struct smb_request *req)
4834 connection_struct *conn = req->conn;
4835 uint64_t count,offset;
4839 START_PROFILE(SMBunlock);
4842 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4843 END_PROFILE(SMBunlock);
4847 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4849 if (!check_fsp(conn, req, fsp)) {
4850 END_PROFILE(SMBunlock);
4854 count = (uint64_t)IVAL(req->vwv+1, 0);
4855 offset = (uint64_t)IVAL(req->vwv+3, 0);
4857 status = do_unlock(smbd_messaging_context(),
4864 if (NT_STATUS_V(status)) {
4865 reply_nterror(req, status);
4866 END_PROFILE(SMBunlock);
4870 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4871 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4873 reply_outbuf(req, 0, 0);
4875 END_PROFILE(SMBunlock);
4880 #define DBGC_CLASS DBGC_ALL
4882 /****************************************************************************
4884 conn POINTER CAN BE NULL HERE !
4885 ****************************************************************************/
4887 void reply_tdis(struct smb_request *req)
4889 connection_struct *conn = req->conn;
4890 START_PROFILE(SMBtdis);
4893 DEBUG(4,("Invalid connection in tdis\n"));
4894 reply_doserror(req, ERRSRV, ERRinvnid);
4895 END_PROFILE(SMBtdis);
4901 close_cnum(conn,req->vuid);
4904 reply_outbuf(req, 0, 0);
4905 END_PROFILE(SMBtdis);
4909 /****************************************************************************
4911 conn POINTER CAN BE NULL HERE !
4912 ****************************************************************************/
4914 void reply_echo(struct smb_request *req)
4916 connection_struct *conn = req->conn;
4917 struct smb_perfcount_data local_pcd;
4918 struct smb_perfcount_data *cur_pcd;
4922 START_PROFILE(SMBecho);
4924 smb_init_perfcount_data(&local_pcd);
4927 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4928 END_PROFILE(SMBecho);
4932 smb_reverb = SVAL(req->vwv+0, 0);
4934 reply_outbuf(req, 1, req->buflen);
4936 /* copy any incoming data back out */
4937 if (req->buflen > 0) {
4938 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4941 if (smb_reverb > 100) {
4942 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4946 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4948 /* this makes sure we catch the request pcd */
4949 if (seq_num == smb_reverb) {
4950 cur_pcd = &req->pcd;
4952 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4953 cur_pcd = &local_pcd;
4956 SSVAL(req->outbuf,smb_vwv0,seq_num);
4958 show_msg((char *)req->outbuf);
4959 if (!srv_send_smb(smbd_server_fd(),
4960 (char *)req->outbuf,
4961 true, req->seqnum+1,
4962 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4964 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4967 DEBUG(3,("echo %d times\n", smb_reverb));
4969 TALLOC_FREE(req->outbuf);
4971 END_PROFILE(SMBecho);
4975 /****************************************************************************
4976 Reply to a printopen.
4977 ****************************************************************************/
4979 void reply_printopen(struct smb_request *req)
4981 connection_struct *conn = req->conn;
4985 START_PROFILE(SMBsplopen);
4988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4989 END_PROFILE(SMBsplopen);
4993 if (!CAN_PRINT(conn)) {
4994 reply_doserror(req, ERRDOS, ERRnoaccess);
4995 END_PROFILE(SMBsplopen);
4999 status = file_new(req, conn, &fsp);
5000 if(!NT_STATUS_IS_OK(status)) {
5001 reply_nterror(req, status);
5002 END_PROFILE(SMBsplopen);
5006 /* Open for exclusive use, write only. */
5007 status = print_fsp_open(req, conn, NULL, req->vuid, fsp);
5009 if (!NT_STATUS_IS_OK(status)) {
5010 file_free(req, fsp);
5011 reply_nterror(req, status);
5012 END_PROFILE(SMBsplopen);
5016 reply_outbuf(req, 1, 0);
5017 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5019 DEBUG(3,("openprint fd=%d fnum=%d\n",
5020 fsp->fh->fd, fsp->fnum));
5022 END_PROFILE(SMBsplopen);
5026 /****************************************************************************
5027 Reply to a printclose.
5028 ****************************************************************************/
5030 void reply_printclose(struct smb_request *req)
5032 connection_struct *conn = req->conn;
5036 START_PROFILE(SMBsplclose);
5039 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5040 END_PROFILE(SMBsplclose);
5044 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5046 if (!check_fsp(conn, req, fsp)) {
5047 END_PROFILE(SMBsplclose);
5051 if (!CAN_PRINT(conn)) {
5052 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
5053 END_PROFILE(SMBsplclose);
5057 DEBUG(3,("printclose fd=%d fnum=%d\n",
5058 fsp->fh->fd,fsp->fnum));
5060 status = close_file(req, fsp, NORMAL_CLOSE);
5062 if(!NT_STATUS_IS_OK(status)) {
5063 reply_nterror(req, status);
5064 END_PROFILE(SMBsplclose);
5068 reply_outbuf(req, 0, 0);
5070 END_PROFILE(SMBsplclose);
5074 /****************************************************************************
5075 Reply to a printqueue.
5076 ****************************************************************************/
5078 void reply_printqueue(struct smb_request *req)
5080 connection_struct *conn = req->conn;
5084 START_PROFILE(SMBsplretq);
5087 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5088 END_PROFILE(SMBsplretq);
5092 max_count = SVAL(req->vwv+0, 0);
5093 start_index = SVAL(req->vwv+1, 0);
5095 /* we used to allow the client to get the cnum wrong, but that
5096 is really quite gross and only worked when there was only
5097 one printer - I think we should now only accept it if they
5098 get it right (tridge) */
5099 if (!CAN_PRINT(conn)) {
5100 reply_doserror(req, ERRDOS, ERRnoaccess);
5101 END_PROFILE(SMBsplretq);
5105 reply_outbuf(req, 2, 3);
5106 SSVAL(req->outbuf,smb_vwv0,0);
5107 SSVAL(req->outbuf,smb_vwv1,0);
5108 SCVAL(smb_buf(req->outbuf),0,1);
5109 SSVAL(smb_buf(req->outbuf),1,0);
5111 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5112 start_index, max_count));
5115 print_queue_struct *queue = NULL;
5116 print_status_struct status;
5117 int count = print_queue_status(SNUM(conn), &queue, &status);
5118 int num_to_get = ABS(max_count);
5119 int first = (max_count>0?start_index:start_index+max_count+1);
5125 num_to_get = MIN(num_to_get,count-first);
5128 for (i=first;i<first+num_to_get;i++) {
5132 srv_put_dos_date2(p,0,queue[i].time);
5133 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5134 SSVAL(p,5, queue[i].job);
5135 SIVAL(p,7,queue[i].size);
5137 srvstr_push(blob, req->flags2, p+12,
5138 queue[i].fs_user, 16, STR_ASCII);
5140 if (message_push_blob(
5143 blob, sizeof(blob))) == -1) {
5144 reply_nterror(req, NT_STATUS_NO_MEMORY);
5145 END_PROFILE(SMBsplretq);
5151 SSVAL(req->outbuf,smb_vwv0,count);
5152 SSVAL(req->outbuf,smb_vwv1,
5153 (max_count>0?first+count:first-1));
5154 SCVAL(smb_buf(req->outbuf),0,1);
5155 SSVAL(smb_buf(req->outbuf),1,28*count);
5160 DEBUG(3,("%d entries returned in queue\n",count));
5163 END_PROFILE(SMBsplretq);
5167 /****************************************************************************
5168 Reply to a printwrite.
5169 ****************************************************************************/
5171 void reply_printwrite(struct smb_request *req)
5173 connection_struct *conn = req->conn;
5178 START_PROFILE(SMBsplwr);
5181 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5182 END_PROFILE(SMBsplwr);
5186 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5188 if (!check_fsp(conn, req, fsp)) {
5189 END_PROFILE(SMBsplwr);
5193 if (!CAN_PRINT(conn)) {
5194 reply_doserror(req, ERRDOS, ERRnoaccess);
5195 END_PROFILE(SMBsplwr);
5199 if (!CHECK_WRITE(fsp)) {
5200 reply_doserror(req, ERRDOS, ERRbadaccess);
5201 END_PROFILE(SMBsplwr);
5205 numtowrite = SVAL(req->buf, 1);
5207 if (req->buflen < numtowrite + 3) {
5208 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5209 END_PROFILE(SMBsplwr);
5213 data = (const char *)req->buf + 3;
5215 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5216 reply_nterror(req, map_nt_error_from_unix(errno));
5217 END_PROFILE(SMBsplwr);
5221 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5223 END_PROFILE(SMBsplwr);
5227 /****************************************************************************
5229 ****************************************************************************/
5231 void reply_mkdir(struct smb_request *req)
5233 connection_struct *conn = req->conn;
5234 struct smb_filename *smb_dname = NULL;
5235 char *directory = NULL;
5237 TALLOC_CTX *ctx = talloc_tos();
5239 START_PROFILE(SMBmkdir);
5241 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5242 STR_TERMINATE, &status);
5243 if (!NT_STATUS_IS_OK(status)) {
5244 reply_nterror(req, status);
5248 status = filename_convert(ctx, conn,
5249 req->flags2 & FLAGS2_DFS_PATHNAMES,
5254 if (!NT_STATUS_IS_OK(status)) {
5255 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5256 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5257 ERRSRV, ERRbadpath);
5260 reply_nterror(req, status);
5264 status = create_directory(conn, req, smb_dname);
5266 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5268 if (!NT_STATUS_IS_OK(status)) {
5270 if (!use_nt_status()
5271 && NT_STATUS_EQUAL(status,
5272 NT_STATUS_OBJECT_NAME_COLLISION)) {
5274 * Yes, in the DOS error code case we get a
5275 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5276 * samba4 torture test.
5278 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5281 reply_nterror(req, status);
5285 reply_outbuf(req, 0, 0);
5287 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5289 TALLOC_FREE(smb_dname);
5290 END_PROFILE(SMBmkdir);
5294 /****************************************************************************
5295 Static function used by reply_rmdir to delete an entire directory
5296 tree recursively. Return True on ok, False on fail.
5297 ****************************************************************************/
5299 static bool recursive_rmdir(TALLOC_CTX *ctx,
5300 connection_struct *conn,
5301 struct smb_filename *smb_dname)
5307 struct smb_Dir *dir_hnd;
5309 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5311 dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0);
5315 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5316 struct smb_filename *smb_dname_full = NULL;
5317 char *fullname = NULL;
5318 bool do_break = true;
5321 if (ISDOT(dname) || ISDOTDOT(dname)) {
5326 if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
5332 /* Construct the full name. */
5333 fullname = talloc_asprintf(ctx,
5335 smb_dname->base_name,
5342 status = create_synthetic_smb_fname(talloc_tos(), fullname,
5345 if (!NT_STATUS_IS_OK(status)) {
5349 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5353 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5354 if(!recursive_rmdir(ctx, conn, smb_dname_full)) {
5357 if(SMB_VFS_RMDIR(conn,
5358 smb_dname_full->base_name) != 0) {
5361 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5365 /* Successful iteration. */
5369 TALLOC_FREE(smb_dname_full);
5370 TALLOC_FREE(fullname);
5377 TALLOC_FREE(dir_hnd);
5381 /****************************************************************************
5382 The internals of the rmdir code - called elsewhere.
5383 ****************************************************************************/
5385 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5386 connection_struct *conn,
5387 struct smb_filename *smb_dname)
5392 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5394 /* Might be a symlink. */
5395 if(SMB_VFS_LSTAT(conn, smb_dname) != 0) {
5396 return map_nt_error_from_unix(errno);
5399 if (S_ISLNK(smb_dname->st.st_ex_mode)) {
5400 /* Is what it points to a directory ? */
5401 if(SMB_VFS_STAT(conn, smb_dname) != 0) {
5402 return map_nt_error_from_unix(errno);
5404 if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
5405 return NT_STATUS_NOT_A_DIRECTORY;
5407 ret = SMB_VFS_UNLINK(conn, smb_dname);
5409 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5412 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5413 FILE_NOTIFY_CHANGE_DIR_NAME,
5414 smb_dname->base_name);
5415 return NT_STATUS_OK;
5418 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5420 * Check to see if the only thing in this directory are
5421 * vetoed files/directories. If so then delete them and
5422 * retry. If we fail to delete any of them (and we *don't*
5423 * do a recursive delete) then fail the rmdir.
5427 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5428 smb_dname->base_name, NULL,
5431 if(dir_hnd == NULL) {
5436 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5437 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) {
5441 if (!is_visible_file(conn, smb_dname->base_name, dname,
5446 if(!IS_VETO_PATH(conn, dname)) {
5447 TALLOC_FREE(dir_hnd);
5455 /* We only have veto files/directories.
5456 * Are we allowed to delete them ? */
5458 if(!lp_recursive_veto_delete(SNUM(conn))) {
5459 TALLOC_FREE(dir_hnd);
5464 /* Do a recursive delete. */
5465 RewindDir(dir_hnd,&dirpos);
5466 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5467 struct smb_filename *smb_dname_full = NULL;
5468 char *fullname = NULL;
5469 bool do_break = true;
5472 if (ISDOT(dname) || ISDOTDOT(dname)) {
5476 if (!is_visible_file(conn, smb_dname->base_name, dname,
5482 fullname = talloc_asprintf(ctx,
5484 smb_dname->base_name,
5492 status = create_synthetic_smb_fname(talloc_tos(),
5496 if (!NT_STATUS_IS_OK(status)) {
5497 errno = map_errno_from_nt_status(status);
5501 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5504 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5505 if(!recursive_rmdir(ctx, conn,
5509 if(SMB_VFS_RMDIR(conn,
5510 smb_dname_full->base_name) != 0) {
5513 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5517 /* Successful iteration. */
5521 TALLOC_FREE(fullname);
5522 TALLOC_FREE(smb_dname_full);
5527 TALLOC_FREE(dir_hnd);
5528 /* Retry the rmdir */
5529 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5535 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5536 "%s\n", smb_fname_str_dbg(smb_dname),
5538 return map_nt_error_from_unix(errno);
5541 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5542 FILE_NOTIFY_CHANGE_DIR_NAME,
5543 smb_dname->base_name);
5545 return NT_STATUS_OK;
5548 /****************************************************************************
5550 ****************************************************************************/
5552 void reply_rmdir(struct smb_request *req)
5554 connection_struct *conn = req->conn;
5555 struct smb_filename *smb_dname = NULL;
5556 char *directory = NULL;
5558 TALLOC_CTX *ctx = talloc_tos();
5559 struct smbd_server_connection *sconn = smbd_server_conn;
5561 START_PROFILE(SMBrmdir);
5563 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5564 STR_TERMINATE, &status);
5565 if (!NT_STATUS_IS_OK(status)) {
5566 reply_nterror(req, status);
5570 status = filename_convert(ctx, conn,
5571 req->flags2 & FLAGS2_DFS_PATHNAMES,
5576 if (!NT_STATUS_IS_OK(status)) {
5577 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5578 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5579 ERRSRV, ERRbadpath);
5582 reply_nterror(req, status);
5586 if (is_ntfs_stream_smb_fname(smb_dname)) {
5587 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5591 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5592 status = rmdir_internals(ctx, conn, smb_dname);
5593 if (!NT_STATUS_IS_OK(status)) {
5594 reply_nterror(req, status);
5598 reply_outbuf(req, 0, 0);
5600 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5602 TALLOC_FREE(smb_dname);
5603 END_PROFILE(SMBrmdir);
5607 /*******************************************************************
5608 Resolve wildcards in a filename rename.
5609 ********************************************************************/
5611 static bool resolve_wildcards(TALLOC_CTX *ctx,
5616 char *name2_copy = NULL;
5621 char *p,*p2, *pname1, *pname2;
5623 name2_copy = talloc_strdup(ctx, name2);
5628 pname1 = strrchr_m(name1,'/');
5629 pname2 = strrchr_m(name2_copy,'/');
5631 if (!pname1 || !pname2) {
5635 /* Truncate the copy of name2 at the last '/' */
5638 /* Now go past the '/' */
5642 root1 = talloc_strdup(ctx, pname1);
5643 root2 = talloc_strdup(ctx, pname2);
5645 if (!root1 || !root2) {
5649 p = strrchr_m(root1,'.');
5652 ext1 = talloc_strdup(ctx, p+1);
5654 ext1 = talloc_strdup(ctx, "");
5656 p = strrchr_m(root2,'.');
5659 ext2 = talloc_strdup(ctx, p+1);
5661 ext2 = talloc_strdup(ctx, "");
5664 if (!ext1 || !ext2) {
5672 /* Hmmm. Should this be mb-aware ? */
5675 } else if (*p2 == '*') {
5677 root2 = talloc_asprintf(ctx, "%s%s",
5696 /* Hmmm. Should this be mb-aware ? */
5699 } else if (*p2 == '*') {
5701 ext2 = talloc_asprintf(ctx, "%s%s",
5717 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5722 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5734 /****************************************************************************
5735 Ensure open files have their names updated. Updated to notify other smbd's
5737 ****************************************************************************/
5739 static void rename_open_files(connection_struct *conn,
5740 struct share_mode_lock *lck,
5741 const struct smb_filename *smb_fname_dst)
5744 bool did_rename = False;
5747 for(fsp = file_find_di_first(lck->id); fsp;
5748 fsp = file_find_di_next(fsp)) {
5749 /* fsp_name is a relative path under the fsp. To change this for other
5750 sharepaths we need to manipulate relative paths. */
5751 /* TODO - create the absolute path and manipulate the newname
5752 relative to the sharepath. */
5753 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5756 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5757 "(file_id %s) from %s -> %s\n", fsp->fnum,
5758 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5759 smb_fname_str_dbg(smb_fname_dst)));
5761 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5762 if (NT_STATUS_IS_OK(status)) {
5768 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5769 "for %s\n", file_id_string_tos(&lck->id),
5770 smb_fname_str_dbg(smb_fname_dst)));
5773 /* Send messages to all smbd's (not ourself) that the name has changed. */
5774 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5779 /****************************************************************************
5780 We need to check if the source path is a parent directory of the destination
5781 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5782 refuse the rename with a sharing violation. Under UNIX the above call can
5783 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5784 probably need to check that the client is a Windows one before disallowing
5785 this as a UNIX client (one with UNIX extensions) can know the source is a
5786 symlink and make this decision intelligently. Found by an excellent bug
5787 report from <AndyLiebman@aol.com>.
5788 ****************************************************************************/
5790 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5791 const struct smb_filename *smb_fname_dst)
5793 const char *psrc = smb_fname_src->base_name;
5794 const char *pdst = smb_fname_dst->base_name;
5797 if (psrc[0] == '.' && psrc[1] == '/') {
5800 if (pdst[0] == '.' && pdst[1] == '/') {
5803 if ((slen = strlen(psrc)) > strlen(pdst)) {
5806 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5810 * Do the notify calls from a rename
5813 static void notify_rename(connection_struct *conn, bool is_dir,
5814 const struct smb_filename *smb_fname_src,
5815 const struct smb_filename *smb_fname_dst)
5817 char *parent_dir_src = NULL;
5818 char *parent_dir_dst = NULL;
5821 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5822 : FILE_NOTIFY_CHANGE_FILE_NAME;
5824 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5825 &parent_dir_src, NULL) ||
5826 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5827 &parent_dir_dst, NULL)) {
5831 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5832 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5833 smb_fname_src->base_name);
5834 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5835 smb_fname_dst->base_name);
5838 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5839 smb_fname_src->base_name);
5840 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5841 smb_fname_dst->base_name);
5844 /* this is a strange one. w2k3 gives an additional event for
5845 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5846 files, but not directories */
5848 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5849 FILE_NOTIFY_CHANGE_ATTRIBUTES
5850 |FILE_NOTIFY_CHANGE_CREATION,
5851 smb_fname_dst->base_name);
5854 TALLOC_FREE(parent_dir_src);
5855 TALLOC_FREE(parent_dir_dst);
5858 /****************************************************************************
5859 Rename an open file - given an fsp.
5860 ****************************************************************************/
5862 NTSTATUS rename_internals_fsp(connection_struct *conn,
5864 const struct smb_filename *smb_fname_dst_in,
5866 bool replace_if_exists)
5868 TALLOC_CTX *ctx = talloc_tos();
5869 struct smb_filename *smb_fname_dst = NULL;
5870 NTSTATUS status = NT_STATUS_OK;
5871 struct share_mode_lock *lck = NULL;
5872 bool dst_exists, old_is_stream, new_is_stream;
5874 status = check_name(conn, smb_fname_dst_in->base_name);
5875 if (!NT_STATUS_IS_OK(status)) {
5879 /* Make a copy of the dst smb_fname structs */
5881 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5882 if (!NT_STATUS_IS_OK(status)) {
5886 /* Ensure the dst smb_fname contains a '/' */
5887 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5889 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5890 smb_fname_dst->base_name);
5892 status = NT_STATUS_NO_MEMORY;
5895 TALLOC_FREE(smb_fname_dst->base_name);
5896 smb_fname_dst->base_name = tmp;
5900 * Check for special case with case preserving and not
5901 * case sensitive. If the old last component differs from the original
5902 * last component only by case, then we should allow
5903 * the rename (user is trying to change the case of the
5906 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5907 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5908 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5910 char *fname_dst_lcomp_base_mod = NULL;
5911 struct smb_filename *smb_fname_orig_lcomp = NULL;
5914 * Get the last component of the destination name. Note that
5915 * we guarantee that destination name contains a '/' character
5918 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5919 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5920 if (!fname_dst_lcomp_base_mod) {
5921 status = NT_STATUS_NO_MEMORY;
5926 * Create an smb_filename struct using the original last
5927 * component of the destination.
5929 status = create_synthetic_smb_fname_split(ctx,
5930 smb_fname_dst->original_lcomp, NULL,
5931 &smb_fname_orig_lcomp);
5932 if (!NT_STATUS_IS_OK(status)) {
5933 TALLOC_FREE(fname_dst_lcomp_base_mod);
5937 /* If the base names only differ by case, use original. */
5938 if(!strcsequal(fname_dst_lcomp_base_mod,
5939 smb_fname_orig_lcomp->base_name)) {
5942 * Replace the modified last component with the
5945 *last_slash = '\0'; /* Truncate at the '/' */
5946 tmp = talloc_asprintf(smb_fname_dst,
5948 smb_fname_dst->base_name,
5949 smb_fname_orig_lcomp->base_name);
5951 status = NT_STATUS_NO_MEMORY;
5952 TALLOC_FREE(fname_dst_lcomp_base_mod);
5953 TALLOC_FREE(smb_fname_orig_lcomp);
5956 TALLOC_FREE(smb_fname_dst->base_name);
5957 smb_fname_dst->base_name = tmp;
5960 /* If the stream_names only differ by case, use original. */
5961 if(!strcsequal(smb_fname_dst->stream_name,
5962 smb_fname_orig_lcomp->stream_name)) {
5964 /* Use the original stream. */
5965 tmp = talloc_strdup(smb_fname_dst,
5966 smb_fname_orig_lcomp->stream_name);
5968 status = NT_STATUS_NO_MEMORY;
5969 TALLOC_FREE(fname_dst_lcomp_base_mod);
5970 TALLOC_FREE(smb_fname_orig_lcomp);
5973 TALLOC_FREE(smb_fname_dst->stream_name);
5974 smb_fname_dst->stream_name = tmp;
5976 TALLOC_FREE(fname_dst_lcomp_base_mod);
5977 TALLOC_FREE(smb_fname_orig_lcomp);
5981 * If the src and dest names are identical - including case,
5982 * don't do the rename, just return success.
5985 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5986 strcsequal(fsp->fsp_name->stream_name,
5987 smb_fname_dst->stream_name)) {
5988 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5989 "- returning success\n",
5990 smb_fname_str_dbg(smb_fname_dst)));
5991 status = NT_STATUS_OK;
5995 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
5996 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5998 /* Return the correct error code if both names aren't streams. */
5999 if (!old_is_stream && new_is_stream) {
6000 status = NT_STATUS_OBJECT_NAME_INVALID;
6004 if (old_is_stream && !new_is_stream) {
6005 status = NT_STATUS_INVALID_PARAMETER;
6009 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6011 if(!replace_if_exists && dst_exists) {
6012 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6013 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6014 smb_fname_str_dbg(smb_fname_dst)));
6015 status = NT_STATUS_OBJECT_NAME_COLLISION;
6020 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6021 &smb_fname_dst->st);
6022 files_struct *dst_fsp = file_find_di_first(fileid);
6023 /* The file can be open when renaming a stream */
6024 if (dst_fsp && !new_is_stream) {
6025 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6026 status = NT_STATUS_ACCESS_DENIED;
6031 /* Ensure we have a valid stat struct for the source. */
6032 status = vfs_stat_fsp(fsp);
6033 if (!NT_STATUS_IS_OK(status)) {
6037 status = can_rename(conn, fsp, attrs, &fsp->fsp_name->st);
6039 if (!NT_STATUS_IS_OK(status)) {
6040 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6041 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6042 smb_fname_str_dbg(smb_fname_dst)));
6043 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6044 status = NT_STATUS_ACCESS_DENIED;
6048 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6049 status = NT_STATUS_ACCESS_DENIED;
6052 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6056 * We have the file open ourselves, so not being able to get the
6057 * corresponding share mode lock is a fatal error.
6060 SMB_ASSERT(lck != NULL);
6062 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6063 uint32 create_options = fsp->fh->private_options;
6065 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6066 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6067 smb_fname_str_dbg(smb_fname_dst)));
6069 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6072 rename_open_files(conn, lck, smb_fname_dst);
6075 * A rename acts as a new file create w.r.t. allowing an initial delete
6076 * on close, probably because in Windows there is a new handle to the
6077 * new file. If initial delete on close was requested but not
6078 * originally set, we need to set it here. This is probably not 100% correct,
6079 * but will work for the CIFSFS client which in non-posix mode
6080 * depends on these semantics. JRA.
6083 if (create_options & FILE_DELETE_ON_CLOSE) {
6084 status = can_set_delete_on_close(fsp, True, 0);
6086 if (NT_STATUS_IS_OK(status)) {
6087 /* Note that here we set the *inital* delete on close flag,
6088 * not the regular one. The magic gets handled in close. */
6089 fsp->initial_delete_on_close = True;
6093 status = NT_STATUS_OK;
6099 if (errno == ENOTDIR || errno == EISDIR) {
6100 status = NT_STATUS_OBJECT_NAME_COLLISION;
6102 status = map_nt_error_from_unix(errno);
6105 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6106 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6107 smb_fname_str_dbg(smb_fname_dst)));
6110 TALLOC_FREE(smb_fname_dst);
6115 /****************************************************************************
6116 The guts of the rename command, split out so it may be called by the NT SMB
6118 ****************************************************************************/
6120 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6121 connection_struct *conn,
6122 struct smb_request *req,
6123 struct smb_filename *smb_fname_src,
6124 struct smb_filename *smb_fname_dst,
6126 bool replace_if_exists,
6129 uint32_t access_mask)
6131 char *fname_src_dir = NULL;
6132 char *fname_src_mask = NULL;
6134 NTSTATUS status = NT_STATUS_OK;
6135 struct smb_Dir *dir_hnd = NULL;
6138 int create_options = 0;
6139 bool posix_pathnames = lp_posix_pathnames();
6142 * Split the old name into directory and last component
6143 * strings. Note that unix_convert may have stripped off a
6144 * leading ./ from both name and newname if the rename is
6145 * at the root of the share. We need to make sure either both
6146 * name and newname contain a / character or neither of them do
6147 * as this is checked in resolve_wildcards().
6150 /* Split up the directory from the filename/mask. */
6151 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6152 &fname_src_dir, &fname_src_mask);
6153 if (!NT_STATUS_IS_OK(status)) {
6154 status = NT_STATUS_NO_MEMORY;
6159 * We should only check the mangled cache
6160 * here if unix_convert failed. This means
6161 * that the path in 'mask' doesn't exist
6162 * on the file system and so we need to look
6163 * for a possible mangle. This patch from
6164 * Tine Smukavec <valentin.smukavec@hermes.si>.
6167 if (!VALID_STAT(smb_fname_src->st) &&
6168 mangle_is_mangled(fname_src_mask, conn->params)) {
6169 char *new_mask = NULL;
6170 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6173 TALLOC_FREE(fname_src_mask);
6174 fname_src_mask = new_mask;
6178 if (!src_has_wild) {
6182 * Only one file needs to be renamed. Append the mask back
6183 * onto the directory.
6185 TALLOC_FREE(smb_fname_src->base_name);
6186 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6190 if (!smb_fname_src->base_name) {
6191 status = NT_STATUS_NO_MEMORY;
6195 /* Ensure dst fname contains a '/' also */
6196 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6198 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6199 smb_fname_dst->base_name);
6201 status = NT_STATUS_NO_MEMORY;
6204 TALLOC_FREE(smb_fname_dst->base_name);
6205 smb_fname_dst->base_name = tmp;
6208 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6209 "case_preserve = %d, short case preserve = %d, "
6210 "directory = %s, newname = %s, "
6211 "last_component_dest = %s\n",
6212 conn->case_sensitive, conn->case_preserve,
6213 conn->short_case_preserve,
6214 smb_fname_str_dbg(smb_fname_src),
6215 smb_fname_str_dbg(smb_fname_dst),
6216 smb_fname_dst->original_lcomp));
6218 /* The dest name still may have wildcards. */
6219 if (dest_has_wild) {
6220 char *fname_dst_mod = NULL;
6221 if (!resolve_wildcards(smb_fname_dst,
6222 smb_fname_src->base_name,
6223 smb_fname_dst->base_name,
6225 DEBUG(6, ("rename_internals: resolve_wildcards "
6227 smb_fname_src->base_name,
6228 smb_fname_dst->base_name));
6229 status = NT_STATUS_NO_MEMORY;
6232 TALLOC_FREE(smb_fname_dst->base_name);
6233 smb_fname_dst->base_name = fname_dst_mod;
6236 ZERO_STRUCT(smb_fname_src->st);
6237 if (posix_pathnames) {
6238 SMB_VFS_LSTAT(conn, smb_fname_src);
6240 SMB_VFS_STAT(conn, smb_fname_src);
6243 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6244 create_options |= FILE_DIRECTORY_FILE;
6247 status = SMB_VFS_CREATE_FILE(
6250 0, /* root_dir_fid */
6251 smb_fname_src, /* fname */
6252 access_mask, /* access_mask */
6253 (FILE_SHARE_READ | /* share_access */
6255 FILE_OPEN, /* create_disposition*/
6256 create_options, /* create_options */
6257 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6258 0, /* oplock_request */
6259 0, /* allocation_size */
6265 if (!NT_STATUS_IS_OK(status)) {
6266 DEBUG(3, ("Could not open rename source %s: %s\n",
6267 smb_fname_str_dbg(smb_fname_src),
6268 nt_errstr(status)));
6272 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6273 attrs, replace_if_exists);
6275 close_file(req, fsp, NORMAL_CLOSE);
6277 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6278 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6279 smb_fname_str_dbg(smb_fname_dst)));
6285 * Wildcards - process each file that matches.
6287 if (strequal(fname_src_mask, "????????.???")) {
6288 TALLOC_FREE(fname_src_mask);
6289 fname_src_mask = talloc_strdup(ctx, "*");
6290 if (!fname_src_mask) {
6291 status = NT_STATUS_NO_MEMORY;
6296 status = check_name(conn, fname_src_dir);
6297 if (!NT_STATUS_IS_OK(status)) {
6301 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6303 if (dir_hnd == NULL) {
6304 status = map_nt_error_from_unix(errno);
6308 status = NT_STATUS_NO_SUCH_FILE;
6310 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6311 * - gentest fix. JRA
6314 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
6315 files_struct *fsp = NULL;
6316 char *destname = NULL;
6317 bool sysdir_entry = False;
6319 /* Quick check for "." and ".." */
6320 if (ISDOT(dname) || ISDOTDOT(dname)) {
6322 sysdir_entry = True;
6329 if (!is_visible_file(conn, fname_src_dir, dname,
6330 &smb_fname_src->st, false)) {
6335 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6341 status = NT_STATUS_OBJECT_NAME_INVALID;
6345 TALLOC_FREE(smb_fname_src->base_name);
6346 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6350 if (!smb_fname_src->base_name) {
6351 status = NT_STATUS_NO_MEMORY;
6355 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6356 smb_fname_dst->base_name,
6358 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6359 smb_fname_src->base_name, destname));
6364 status = NT_STATUS_NO_MEMORY;
6368 TALLOC_FREE(smb_fname_dst->base_name);
6369 smb_fname_dst->base_name = destname;
6371 ZERO_STRUCT(smb_fname_src->st);
6372 if (posix_pathnames) {
6373 SMB_VFS_LSTAT(conn, smb_fname_src);
6375 SMB_VFS_STAT(conn, smb_fname_src);
6380 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6381 create_options |= FILE_DIRECTORY_FILE;
6384 status = SMB_VFS_CREATE_FILE(
6387 0, /* root_dir_fid */
6388 smb_fname_src, /* fname */
6389 access_mask, /* access_mask */
6390 (FILE_SHARE_READ | /* share_access */
6392 FILE_OPEN, /* create_disposition*/
6393 create_options, /* create_options */
6394 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6395 0, /* oplock_request */
6396 0, /* allocation_size */
6402 if (!NT_STATUS_IS_OK(status)) {
6403 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6404 "returned %s rename %s -> %s\n",
6406 smb_fname_str_dbg(smb_fname_src),
6407 smb_fname_str_dbg(smb_fname_dst)));
6411 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6413 if (!smb_fname_dst->original_lcomp) {
6414 status = NT_STATUS_NO_MEMORY;
6418 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6419 attrs, replace_if_exists);
6421 close_file(req, fsp, NORMAL_CLOSE);
6423 if (!NT_STATUS_IS_OK(status)) {
6424 DEBUG(3, ("rename_internals_fsp returned %s for "
6425 "rename %s -> %s\n", nt_errstr(status),
6426 smb_fname_str_dbg(smb_fname_src),
6427 smb_fname_str_dbg(smb_fname_dst)));
6433 DEBUG(3,("rename_internals: doing rename on %s -> "
6434 "%s\n", smb_fname_str_dbg(smb_fname_src),
6435 smb_fname_str_dbg(smb_fname_src)));
6438 TALLOC_FREE(dir_hnd);
6440 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6441 status = map_nt_error_from_unix(errno);
6446 TALLOC_FREE(fname_src_dir);
6447 TALLOC_FREE(fname_src_mask);
6451 /****************************************************************************
6453 ****************************************************************************/
6455 void reply_mv(struct smb_request *req)
6457 connection_struct *conn = req->conn;
6459 char *newname = NULL;
6463 bool src_has_wcard = False;
6464 bool dest_has_wcard = False;
6465 TALLOC_CTX *ctx = talloc_tos();
6466 struct smb_filename *smb_fname_src = NULL;
6467 struct smb_filename *smb_fname_dst = NULL;
6469 START_PROFILE(SMBmv);
6472 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6476 attrs = SVAL(req->vwv+0, 0);
6478 p = (const char *)req->buf + 1;
6479 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6480 &status, &src_has_wcard);
6481 if (!NT_STATUS_IS_OK(status)) {
6482 reply_nterror(req, status);
6486 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6487 &status, &dest_has_wcard);
6488 if (!NT_STATUS_IS_OK(status)) {
6489 reply_nterror(req, status);
6493 status = filename_convert(ctx,
6495 req->flags2 & FLAGS2_DFS_PATHNAMES,
6497 UCF_COND_ALLOW_WCARD_LCOMP,
6501 if (!NT_STATUS_IS_OK(status)) {
6502 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6503 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6504 ERRSRV, ERRbadpath);
6507 reply_nterror(req, status);
6511 status = filename_convert(ctx,
6513 req->flags2 & FLAGS2_DFS_PATHNAMES,
6515 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6519 if (!NT_STATUS_IS_OK(status)) {
6520 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6521 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6522 ERRSRV, ERRbadpath);
6525 reply_nterror(req, status);
6529 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6530 smb_fname_str_dbg(smb_fname_dst)));
6532 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6533 attrs, False, src_has_wcard, dest_has_wcard,
6535 if (!NT_STATUS_IS_OK(status)) {
6536 if (open_was_deferred(req->mid)) {
6537 /* We have re-scheduled this call. */
6540 reply_nterror(req, status);
6544 reply_outbuf(req, 0, 0);
6546 TALLOC_FREE(smb_fname_src);
6547 TALLOC_FREE(smb_fname_dst);
6552 /*******************************************************************
6553 Copy a file as part of a reply_copy.
6554 ******************************************************************/
6557 * TODO: check error codes on all callers
6560 NTSTATUS copy_file(TALLOC_CTX *ctx,
6561 connection_struct *conn,
6562 struct smb_filename *smb_fname_src,
6563 struct smb_filename *smb_fname_dst,
6566 bool target_is_directory)
6568 struct smb_filename *smb_fname_dst_tmp = NULL;
6570 files_struct *fsp1,*fsp2;
6572 uint32 new_create_disposition;
6576 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6577 if (!NT_STATUS_IS_OK(status)) {
6582 * If the target is a directory, extract the last component from the
6583 * src filename and append it to the dst filename
6585 if (target_is_directory) {
6588 /* dest/target can't be a stream if it's a directory. */
6589 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6591 p = strrchr_m(smb_fname_src->base_name,'/');
6595 p = smb_fname_src->base_name;
6597 smb_fname_dst_tmp->base_name =
6598 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6600 if (!smb_fname_dst_tmp->base_name) {
6601 status = NT_STATUS_NO_MEMORY;
6606 status = vfs_file_exist(conn, smb_fname_src);
6607 if (!NT_STATUS_IS_OK(status)) {
6611 if (!target_is_directory && count) {
6612 new_create_disposition = FILE_OPEN;
6614 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6616 &new_create_disposition,
6618 status = NT_STATUS_INVALID_PARAMETER;
6623 /* Open the src file for reading. */
6624 status = SMB_VFS_CREATE_FILE(
6627 0, /* root_dir_fid */
6628 smb_fname_src, /* fname */
6629 FILE_GENERIC_READ, /* access_mask */
6630 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6631 FILE_OPEN, /* create_disposition*/
6632 0, /* create_options */
6633 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6634 INTERNAL_OPEN_ONLY, /* oplock_request */
6635 0, /* allocation_size */
6641 if (!NT_STATUS_IS_OK(status)) {
6645 dosattrs = dos_mode(conn, smb_fname_src);
6647 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6648 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6651 /* Open the dst file for writing. */
6652 status = SMB_VFS_CREATE_FILE(
6655 0, /* root_dir_fid */
6656 smb_fname_dst, /* fname */
6657 FILE_GENERIC_WRITE, /* access_mask */
6658 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6659 new_create_disposition, /* create_disposition*/
6660 0, /* create_options */
6661 dosattrs, /* file_attributes */
6662 INTERNAL_OPEN_ONLY, /* oplock_request */
6663 0, /* allocation_size */
6669 if (!NT_STATUS_IS_OK(status)) {
6670 close_file(NULL, fsp1, ERROR_CLOSE);
6674 if ((ofun&3) == 1) {
6675 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6676 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6678 * Stop the copy from occurring.
6681 smb_fname_src->st.st_ex_size = 0;
6685 /* Do the actual copy. */
6686 if (smb_fname_src->st.st_ex_size) {
6687 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6690 close_file(NULL, fsp1, NORMAL_CLOSE);
6692 /* Ensure the modtime is set correctly on the destination file. */
6693 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6696 * As we are opening fsp1 read-only we only expect
6697 * an error on close on fsp2 if we are out of space.
6698 * Thus we don't look at the error return from the
6701 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6703 if (!NT_STATUS_IS_OK(status)) {
6707 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6708 status = NT_STATUS_DISK_FULL;
6712 status = NT_STATUS_OK;
6715 TALLOC_FREE(smb_fname_dst_tmp);
6719 /****************************************************************************
6720 Reply to a file copy.
6721 ****************************************************************************/
6723 void reply_copy(struct smb_request *req)
6725 connection_struct *conn = req->conn;
6726 struct smb_filename *smb_fname_src = NULL;
6727 struct smb_filename *smb_fname_dst = NULL;
6728 char *fname_src = NULL;
6729 char *fname_dst = NULL;
6730 char *fname_src_mask = NULL;
6731 char *fname_src_dir = NULL;
6734 int error = ERRnoaccess;
6738 bool target_is_directory=False;
6739 bool source_has_wild = False;
6740 bool dest_has_wild = False;
6742 TALLOC_CTX *ctx = talloc_tos();
6744 START_PROFILE(SMBcopy);
6747 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6751 tid2 = SVAL(req->vwv+0, 0);
6752 ofun = SVAL(req->vwv+1, 0);
6753 flags = SVAL(req->vwv+2, 0);
6755 p = (const char *)req->buf;
6756 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6757 &status, &source_has_wild);
6758 if (!NT_STATUS_IS_OK(status)) {
6759 reply_nterror(req, status);
6762 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6763 &status, &dest_has_wild);
6764 if (!NT_STATUS_IS_OK(status)) {
6765 reply_nterror(req, status);
6769 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6771 if (tid2 != conn->cnum) {
6772 /* can't currently handle inter share copies XXXX */
6773 DEBUG(3,("Rejecting inter-share copy\n"));
6774 reply_doserror(req, ERRSRV, ERRinvdevice);
6778 status = filename_convert(ctx, conn,
6779 req->flags2 & FLAGS2_DFS_PATHNAMES,
6781 UCF_COND_ALLOW_WCARD_LCOMP,
6784 if (!NT_STATUS_IS_OK(status)) {
6785 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6786 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6787 ERRSRV, ERRbadpath);
6790 reply_nterror(req, status);
6794 status = filename_convert(ctx, conn,
6795 req->flags2 & FLAGS2_DFS_PATHNAMES,
6797 UCF_COND_ALLOW_WCARD_LCOMP,
6800 if (!NT_STATUS_IS_OK(status)) {
6801 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6802 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6803 ERRSRV, ERRbadpath);
6806 reply_nterror(req, status);
6810 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6812 if ((flags&1) && target_is_directory) {
6813 reply_doserror(req, ERRDOS, ERRbadfile);
6817 if ((flags&2) && !target_is_directory) {
6818 reply_doserror(req, ERRDOS, ERRbadpath);
6822 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6823 /* wants a tree copy! XXXX */
6824 DEBUG(3,("Rejecting tree copy\n"));
6825 reply_doserror(req, ERRSRV, ERRerror);
6829 /* Split up the directory from the filename/mask. */
6830 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6831 &fname_src_dir, &fname_src_mask);
6832 if (!NT_STATUS_IS_OK(status)) {
6833 reply_nterror(req, NT_STATUS_NO_MEMORY);
6838 * We should only check the mangled cache
6839 * here if unix_convert failed. This means
6840 * that the path in 'mask' doesn't exist
6841 * on the file system and so we need to look
6842 * for a possible mangle. This patch from
6843 * Tine Smukavec <valentin.smukavec@hermes.si>.
6845 if (!VALID_STAT(smb_fname_src->st) &&
6846 mangle_is_mangled(fname_src_mask, conn->params)) {
6847 char *new_mask = NULL;
6848 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6849 &new_mask, conn->params);
6851 /* Use demangled name if one was successfully found. */
6853 TALLOC_FREE(fname_src_mask);
6854 fname_src_mask = new_mask;
6858 if (!source_has_wild) {
6861 * Only one file needs to be copied. Append the mask back onto
6864 TALLOC_FREE(smb_fname_src->base_name);
6865 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6869 if (!smb_fname_src->base_name) {
6870 reply_nterror(req, NT_STATUS_NO_MEMORY);
6874 if (dest_has_wild) {
6875 char *fname_dst_mod = NULL;
6876 if (!resolve_wildcards(smb_fname_dst,
6877 smb_fname_src->base_name,
6878 smb_fname_dst->base_name,
6880 reply_nterror(req, NT_STATUS_NO_MEMORY);
6883 TALLOC_FREE(smb_fname_dst->base_name);
6884 smb_fname_dst->base_name = fname_dst_mod;
6887 status = check_name(conn, smb_fname_src->base_name);
6888 if (!NT_STATUS_IS_OK(status)) {
6889 reply_nterror(req, status);
6893 status = check_name(conn, smb_fname_dst->base_name);
6894 if (!NT_STATUS_IS_OK(status)) {
6895 reply_nterror(req, status);
6899 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6900 ofun, count, target_is_directory);
6902 if(!NT_STATUS_IS_OK(status)) {
6903 reply_nterror(req, status);
6909 struct smb_Dir *dir_hnd = NULL;
6914 * There is a wildcard that requires us to actually read the
6915 * src dir and copy each file matching the mask to the dst.
6916 * Right now streams won't be copied, but this could
6917 * presumably be added with a nested loop for reach dir entry.
6919 SMB_ASSERT(!smb_fname_src->stream_name);
6920 SMB_ASSERT(!smb_fname_dst->stream_name);
6922 smb_fname_src->stream_name = NULL;
6923 smb_fname_dst->stream_name = NULL;
6925 if (strequal(fname_src_mask,"????????.???")) {
6926 TALLOC_FREE(fname_src_mask);
6927 fname_src_mask = talloc_strdup(ctx, "*");
6928 if (!fname_src_mask) {
6929 reply_nterror(req, NT_STATUS_NO_MEMORY);
6934 status = check_name(conn, fname_src_dir);
6935 if (!NT_STATUS_IS_OK(status)) {
6936 reply_nterror(req, status);
6940 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6941 if (dir_hnd == NULL) {
6942 status = map_nt_error_from_unix(errno);
6943 reply_nterror(req, status);
6949 /* Iterate over the src dir copying each entry to the dst. */
6950 while ((dname = ReadDirName(dir_hnd, &offset,
6951 &smb_fname_src->st))) {
6952 char *destname = NULL;
6954 if (ISDOT(dname) || ISDOTDOT(dname)) {
6959 if (!is_visible_file(conn, fname_src_dir, dname,
6960 &smb_fname_src->st, false)) {
6965 if(!mask_match(dname, fname_src_mask,
6966 conn->case_sensitive)) {
6971 error = ERRnoaccess;
6973 /* Get the src smb_fname struct setup. */
6974 TALLOC_FREE(smb_fname_src->base_name);
6975 smb_fname_src->base_name =
6976 talloc_asprintf(smb_fname_src, "%s/%s",
6977 fname_src_dir, dname);
6979 if (!smb_fname_src->base_name) {
6980 TALLOC_FREE(dir_hnd);
6982 reply_nterror(req, NT_STATUS_NO_MEMORY);
6986 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6987 smb_fname_dst->base_name,
6993 TALLOC_FREE(dir_hnd);
6995 reply_nterror(req, NT_STATUS_NO_MEMORY);
6999 TALLOC_FREE(smb_fname_dst->base_name);
7000 smb_fname_dst->base_name = destname;
7002 status = check_name(conn, smb_fname_src->base_name);
7003 if (!NT_STATUS_IS_OK(status)) {
7004 TALLOC_FREE(dir_hnd);
7006 reply_nterror(req, status);
7010 status = check_name(conn, smb_fname_dst->base_name);
7011 if (!NT_STATUS_IS_OK(status)) {
7012 TALLOC_FREE(dir_hnd);
7014 reply_nterror(req, status);
7018 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7019 smb_fname_src->base_name,
7020 smb_fname_dst->base_name));
7022 status = copy_file(ctx, conn, smb_fname_src,
7023 smb_fname_dst, ofun, count,
7024 target_is_directory);
7025 if (NT_STATUS_IS_OK(status)) {
7031 TALLOC_FREE(dir_hnd);
7035 reply_doserror(req, ERRDOS, error);
7039 reply_outbuf(req, 1, 0);
7040 SSVAL(req->outbuf,smb_vwv0,count);
7042 TALLOC_FREE(smb_fname_src);
7043 TALLOC_FREE(smb_fname_dst);
7044 TALLOC_FREE(fname_src);
7045 TALLOC_FREE(fname_dst);
7046 TALLOC_FREE(fname_src_mask);
7047 TALLOC_FREE(fname_src_dir);
7049 END_PROFILE(SMBcopy);
7054 #define DBGC_CLASS DBGC_LOCKING
7056 /****************************************************************************
7057 Get a lock pid, dealing with large count requests.
7058 ****************************************************************************/
7060 uint32 get_lock_pid(const uint8_t *data, int data_offset,
7061 bool large_file_format)
7063 if(!large_file_format)
7064 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
7066 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7069 /****************************************************************************
7070 Get a lock count, dealing with large count requests.
7071 ****************************************************************************/
7073 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7074 bool large_file_format)
7078 if(!large_file_format) {
7079 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7082 #if defined(HAVE_LONGLONG)
7083 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7084 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7085 #else /* HAVE_LONGLONG */
7088 * NT4.x seems to be broken in that it sends large file (64 bit)
7089 * lockingX calls even if the CAP_LARGE_FILES was *not*
7090 * negotiated. For boxes without large unsigned ints truncate the
7091 * lock count by dropping the top 32 bits.
7094 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7095 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7096 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7097 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7098 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7101 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7102 #endif /* HAVE_LONGLONG */
7108 #if !defined(HAVE_LONGLONG)
7109 /****************************************************************************
7110 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7111 ****************************************************************************/
7113 static uint32 map_lock_offset(uint32 high, uint32 low)
7117 uint32 highcopy = high;
7120 * Try and find out how many significant bits there are in high.
7123 for(i = 0; highcopy; i++)
7127 * We use 31 bits not 32 here as POSIX
7128 * lock offsets may not be negative.
7131 mask = (~0) << (31 - i);
7134 return 0; /* Fail. */
7140 #endif /* !defined(HAVE_LONGLONG) */
7142 /****************************************************************************
7143 Get a lock offset, dealing with large offset requests.
7144 ****************************************************************************/
7146 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7147 bool large_file_format, bool *err)
7149 uint64_t offset = 0;
7153 if(!large_file_format) {
7154 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7157 #if defined(HAVE_LONGLONG)
7158 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7159 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7160 #else /* HAVE_LONGLONG */
7163 * NT4.x seems to be broken in that it sends large file (64 bit)
7164 * lockingX calls even if the CAP_LARGE_FILES was *not*
7165 * negotiated. For boxes without large unsigned ints mangle the
7166 * lock offset by mapping the top 32 bits onto the lower 32.
7169 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7170 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7171 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7174 if((new_low = map_lock_offset(high, low)) == 0) {
7176 return (uint64_t)-1;
7179 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7180 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7181 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7182 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7185 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7186 #endif /* HAVE_LONGLONG */
7192 NTSTATUS smbd_do_locking(struct smb_request *req,
7196 uint16_t num_ulocks,
7197 struct smbd_lock_element *ulocks,
7199 struct smbd_lock_element *locks,
7202 connection_struct *conn = req->conn;
7204 NTSTATUS status = NT_STATUS_OK;
7208 /* Data now points at the beginning of the list
7209 of smb_unlkrng structs */
7210 for(i = 0; i < (int)num_ulocks; i++) {
7211 struct smbd_lock_element *e = &ulocks[i];
7213 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7214 "pid %u, file %s\n",
7217 (unsigned int)e->smbpid,
7220 if (e->brltype != UNLOCK_LOCK) {
7221 /* this can only happen with SMB2 */
7222 return NT_STATUS_INVALID_PARAMETER;
7225 status = do_unlock(smbd_messaging_context(),
7232 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7233 nt_errstr(status)));
7235 if (!NT_STATUS_IS_OK(status)) {
7240 /* Setup the timeout in seconds. */
7242 if (!lp_blocking_locks(SNUM(conn))) {
7246 /* Data now points at the beginning of the list
7247 of smb_lkrng structs */
7249 for(i = 0; i < (int)num_locks; i++) {
7250 struct smbd_lock_element *e = &locks[i];
7252 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for pid "
7253 "%u, file %s timeout = %d\n",
7256 (unsigned int)e->smbpid,
7260 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7261 struct blocking_lock_record *blr = NULL;
7263 if (lp_blocking_locks(SNUM(conn))) {
7265 /* Schedule a message to ourselves to
7266 remove the blocking lock record and
7267 return the right error. */
7269 blr = blocking_lock_cancel(fsp,
7275 NT_STATUS_FILE_LOCK_CONFLICT);
7277 return NT_STATUS_DOS(
7279 ERRcancelviolation);
7282 /* Remove a matching pending lock. */
7283 status = do_lock_cancel(fsp,
7290 bool blocking_lock = timeout ? true : false;
7291 bool defer_lock = false;
7292 struct byte_range_lock *br_lck;
7293 uint32_t block_smbpid;
7295 br_lck = do_lock(smbd_messaging_context(),
7307 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7308 /* Windows internal resolution for blocking locks seems
7309 to be about 200ms... Don't wait for less than that. JRA. */
7310 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7311 timeout = lp_lock_spin_time();
7316 /* This heuristic seems to match W2K3 very well. If a
7317 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7318 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7319 far as I can tell. Replacement for do_lock_spin(). JRA. */
7321 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7322 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7324 timeout = lp_lock_spin_time();
7327 if (br_lck && defer_lock) {
7329 * A blocking lock was requested. Package up
7330 * this smb into a queued request and push it
7331 * onto the blocking lock queue.
7333 if(push_blocking_lock_request(br_lck,
7344 TALLOC_FREE(br_lck);
7346 return NT_STATUS_OK;
7350 TALLOC_FREE(br_lck);
7353 if (!NT_STATUS_IS_OK(status)) {
7358 /* If any of the above locks failed, then we must unlock
7359 all of the previous locks (X/Open spec). */
7361 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7363 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7364 i = -1; /* we want to skip the for loop */
7368 * Ensure we don't do a remove on the lock that just failed,
7369 * as under POSIX rules, if we have a lock already there, we
7370 * will delete it (and we shouldn't) .....
7372 for(i--; i >= 0; i--) {
7373 struct smbd_lock_element *e = &locks[i];
7375 do_unlock(smbd_messaging_context(),
7385 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7386 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7388 return NT_STATUS_OK;
7391 /****************************************************************************
7392 Reply to a lockingX request.
7393 ****************************************************************************/
7395 void reply_lockingX(struct smb_request *req)
7397 connection_struct *conn = req->conn;
7399 unsigned char locktype;
7400 unsigned char oplocklevel;
7405 const uint8_t *data;
7406 bool large_file_format;
7408 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7409 struct smbd_lock_element *ulocks;
7410 struct smbd_lock_element *locks;
7413 START_PROFILE(SMBlockingX);
7416 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7417 END_PROFILE(SMBlockingX);
7421 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7422 locktype = CVAL(req->vwv+3, 0);
7423 oplocklevel = CVAL(req->vwv+3, 1);
7424 num_ulocks = SVAL(req->vwv+6, 0);
7425 num_locks = SVAL(req->vwv+7, 0);
7426 lock_timeout = IVAL(req->vwv+4, 0);
7427 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7429 if (!check_fsp(conn, req, fsp)) {
7430 END_PROFILE(SMBlockingX);
7436 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7437 /* we don't support these - and CANCEL_LOCK makes w2k
7438 and XP reboot so I don't really want to be
7439 compatible! (tridge) */
7440 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7441 END_PROFILE(SMBlockingX);
7445 /* Check if this is an oplock break on a file
7446 we have granted an oplock on.
7448 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7449 /* Client can insist on breaking to none. */
7450 bool break_to_none = (oplocklevel == 0);
7453 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7454 "for fnum = %d\n", (unsigned int)oplocklevel,
7458 * Make sure we have granted an exclusive or batch oplock on
7462 if (fsp->oplock_type == 0) {
7464 /* The Samba4 nbench simulator doesn't understand
7465 the difference between break to level2 and break
7466 to none from level2 - it sends oplock break
7467 replies in both cases. Don't keep logging an error
7468 message here - just ignore it. JRA. */
7470 DEBUG(5,("reply_lockingX: Error : oplock break from "
7471 "client for fnum = %d (oplock=%d) and no "
7472 "oplock granted on this file (%s).\n",
7473 fsp->fnum, fsp->oplock_type,
7476 /* if this is a pure oplock break request then don't
7478 if (num_locks == 0 && num_ulocks == 0) {
7479 END_PROFILE(SMBlockingX);
7482 END_PROFILE(SMBlockingX);
7483 reply_doserror(req, ERRDOS, ERRlock);
7488 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7490 result = remove_oplock(fsp);
7492 result = downgrade_oplock(fsp);
7496 DEBUG(0, ("reply_lockingX: error in removing "
7497 "oplock on file %s\n", fsp_str_dbg(fsp)));
7498 /* Hmmm. Is this panic justified? */
7499 smb_panic("internal tdb error");
7502 reply_to_oplock_break_requests(fsp);
7504 /* if this is a pure oplock break request then don't send a
7506 if (num_locks == 0 && num_ulocks == 0) {
7507 /* Sanity check - ensure a pure oplock break is not a
7509 if(CVAL(req->vwv+0, 0) != 0xff)
7510 DEBUG(0,("reply_lockingX: Error : pure oplock "
7511 "break is a chained %d request !\n",
7512 (unsigned int)CVAL(req->vwv+0, 0)));
7513 END_PROFILE(SMBlockingX);
7519 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7520 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7521 END_PROFILE(SMBlockingX);
7525 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7526 if (ulocks == NULL) {
7527 reply_nterror(req, NT_STATUS_NO_MEMORY);
7528 END_PROFILE(SMBlockingX);
7532 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7533 if (locks == NULL) {
7534 reply_nterror(req, NT_STATUS_NO_MEMORY);
7535 END_PROFILE(SMBlockingX);
7539 /* Data now points at the beginning of the list
7540 of smb_unlkrng structs */
7541 for(i = 0; i < (int)num_ulocks; i++) {
7542 ulocks[i].smbpid = get_lock_pid(data, i, large_file_format);
7543 ulocks[i].count = get_lock_count(data, i, large_file_format);
7544 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7545 ulocks[i].brltype = UNLOCK_LOCK;
7548 * There is no error code marked "stupid client bug".... :-).
7551 END_PROFILE(SMBlockingX);
7552 reply_doserror(req, ERRDOS, ERRnoaccess);
7557 /* Now do any requested locks */
7558 data += ((large_file_format ? 20 : 10)*num_ulocks);
7560 /* Data now points at the beginning of the list
7561 of smb_lkrng structs */
7563 for(i = 0; i < (int)num_locks; i++) {
7564 locks[i].smbpid = get_lock_pid(data, i, large_file_format);
7565 locks[i].count = get_lock_count(data, i, large_file_format);
7566 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7568 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7569 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7570 locks[i].brltype = PENDING_READ_LOCK;
7572 locks[i].brltype = READ_LOCK;
7575 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7576 locks[i].brltype = PENDING_WRITE_LOCK;
7578 locks[i].brltype = WRITE_LOCK;
7583 * There is no error code marked "stupid client bug".... :-).
7586 END_PROFILE(SMBlockingX);
7587 reply_doserror(req, ERRDOS, ERRnoaccess);
7592 status = smbd_do_locking(req, fsp,
7593 locktype, lock_timeout,
7597 if (!NT_STATUS_IS_OK(status)) {
7598 END_PROFILE(SMBlockingX);
7599 reply_nterror(req, status);
7603 END_PROFILE(SMBlockingX);
7607 reply_outbuf(req, 2, 0);
7609 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7610 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7612 END_PROFILE(SMBlockingX);
7617 #define DBGC_CLASS DBGC_ALL
7619 /****************************************************************************
7620 Reply to a SMBreadbmpx (read block multiplex) request.
7621 Always reply with an error, if someone has a platform really needs this,
7622 please contact vl@samba.org
7623 ****************************************************************************/
7625 void reply_readbmpx(struct smb_request *req)
7627 START_PROFILE(SMBreadBmpx);
7628 reply_doserror(req, ERRSRV, ERRuseSTD);
7629 END_PROFILE(SMBreadBmpx);
7633 /****************************************************************************
7634 Reply to a SMBreadbs (read block multiplex secondary) request.
7635 Always reply with an error, if someone has a platform really needs this,
7636 please contact vl@samba.org
7637 ****************************************************************************/
7639 void reply_readbs(struct smb_request *req)
7641 START_PROFILE(SMBreadBs);
7642 reply_doserror(req, ERRSRV, ERRuseSTD);
7643 END_PROFILE(SMBreadBs);
7647 /****************************************************************************
7648 Reply to a SMBsetattrE.
7649 ****************************************************************************/
7651 void reply_setattrE(struct smb_request *req)
7653 connection_struct *conn = req->conn;
7654 struct smb_file_time ft;
7658 START_PROFILE(SMBsetattrE);
7662 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7666 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7668 if(!fsp || (fsp->conn != conn)) {
7669 reply_doserror(req, ERRDOS, ERRbadfid);
7674 * Convert the DOS times into unix times.
7677 ft.atime = convert_time_t_to_timespec(
7678 srv_make_unix_date2(req->vwv+3));
7679 ft.mtime = convert_time_t_to_timespec(
7680 srv_make_unix_date2(req->vwv+5));
7681 ft.create_time = convert_time_t_to_timespec(
7682 srv_make_unix_date2(req->vwv+1));
7684 reply_outbuf(req, 0, 0);
7687 * Patch from Ray Frush <frush@engr.colostate.edu>
7688 * Sometimes times are sent as zero - ignore them.
7691 /* Ensure we have a valid stat struct for the source. */
7692 status = vfs_stat_fsp(fsp);
7693 if (!NT_STATUS_IS_OK(status)) {
7694 reply_nterror(req, status);
7698 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7699 if (!NT_STATUS_IS_OK(status)) {
7700 reply_doserror(req, ERRDOS, ERRnoaccess);
7704 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7707 (unsigned int)ft.atime.tv_sec,
7708 (unsigned int)ft.mtime.tv_sec,
7709 (unsigned int)ft.create_time.tv_sec
7712 END_PROFILE(SMBsetattrE);
7717 /* Back from the dead for OS/2..... JRA. */
7719 /****************************************************************************
7720 Reply to a SMBwritebmpx (write block multiplex primary) request.
7721 Always reply with an error, if someone has a platform really needs this,
7722 please contact vl@samba.org
7723 ****************************************************************************/
7725 void reply_writebmpx(struct smb_request *req)
7727 START_PROFILE(SMBwriteBmpx);
7728 reply_doserror(req, ERRSRV, ERRuseSTD);
7729 END_PROFILE(SMBwriteBmpx);
7733 /****************************************************************************
7734 Reply to a SMBwritebs (write block multiplex secondary) request.
7735 Always reply with an error, if someone has a platform really needs this,
7736 please contact vl@samba.org
7737 ****************************************************************************/
7739 void reply_writebs(struct smb_request *req)
7741 START_PROFILE(SMBwriteBs);
7742 reply_doserror(req, ERRSRV, ERRuseSTD);
7743 END_PROFILE(SMBwriteBs);
7747 /****************************************************************************
7748 Reply to a SMBgetattrE.
7749 ****************************************************************************/
7751 void reply_getattrE(struct smb_request *req)
7753 connection_struct *conn = req->conn;
7756 struct timespec create_ts;
7758 START_PROFILE(SMBgetattrE);
7761 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7762 END_PROFILE(SMBgetattrE);
7766 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7768 if(!fsp || (fsp->conn != conn)) {
7769 reply_doserror(req, ERRDOS, ERRbadfid);
7770 END_PROFILE(SMBgetattrE);
7774 /* Do an fstat on this file */
7776 reply_nterror(req, map_nt_error_from_unix(errno));
7777 END_PROFILE(SMBgetattrE);
7781 mode = dos_mode(conn, fsp->fsp_name);
7784 * Convert the times into dos times. Set create
7785 * date to be last modify date as UNIX doesn't save
7789 reply_outbuf(req, 11, 0);
7791 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7792 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7793 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7794 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7795 /* Should we check pending modtime here ? JRA */
7796 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7797 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7800 SIVAL(req->outbuf, smb_vwv6, 0);
7801 SIVAL(req->outbuf, smb_vwv8, 0);
7803 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7804 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7805 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7807 SSVAL(req->outbuf,smb_vwv10, mode);
7809 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7811 END_PROFILE(SMBgetattrE);