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;
4983 SMB_STRUCT_STAT sbuf;
4986 START_PROFILE(SMBsplopen);
4989 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4990 END_PROFILE(SMBsplopen);
4994 if (!CAN_PRINT(conn)) {
4995 reply_doserror(req, ERRDOS, ERRnoaccess);
4996 END_PROFILE(SMBsplopen);
5000 status = file_new(req, conn, &fsp);
5001 if(!NT_STATUS_IS_OK(status)) {
5002 reply_nterror(req, status);
5003 END_PROFILE(SMBsplopen);
5007 /* Open for exclusive use, write only. */
5008 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
5010 if (!NT_STATUS_IS_OK(status)) {
5011 file_free(req, fsp);
5012 reply_nterror(req, status);
5013 END_PROFILE(SMBsplopen);
5017 reply_outbuf(req, 1, 0);
5018 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5020 DEBUG(3,("openprint fd=%d fnum=%d\n",
5021 fsp->fh->fd, fsp->fnum));
5023 END_PROFILE(SMBsplopen);
5027 /****************************************************************************
5028 Reply to a printclose.
5029 ****************************************************************************/
5031 void reply_printclose(struct smb_request *req)
5033 connection_struct *conn = req->conn;
5037 START_PROFILE(SMBsplclose);
5040 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5041 END_PROFILE(SMBsplclose);
5045 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5047 if (!check_fsp(conn, req, fsp)) {
5048 END_PROFILE(SMBsplclose);
5052 if (!CAN_PRINT(conn)) {
5053 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
5054 END_PROFILE(SMBsplclose);
5058 DEBUG(3,("printclose fd=%d fnum=%d\n",
5059 fsp->fh->fd,fsp->fnum));
5061 status = close_file(req, fsp, NORMAL_CLOSE);
5063 if(!NT_STATUS_IS_OK(status)) {
5064 reply_nterror(req, status);
5065 END_PROFILE(SMBsplclose);
5069 reply_outbuf(req, 0, 0);
5071 END_PROFILE(SMBsplclose);
5075 /****************************************************************************
5076 Reply to a printqueue.
5077 ****************************************************************************/
5079 void reply_printqueue(struct smb_request *req)
5081 connection_struct *conn = req->conn;
5085 START_PROFILE(SMBsplretq);
5088 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5089 END_PROFILE(SMBsplretq);
5093 max_count = SVAL(req->vwv+0, 0);
5094 start_index = SVAL(req->vwv+1, 0);
5096 /* we used to allow the client to get the cnum wrong, but that
5097 is really quite gross and only worked when there was only
5098 one printer - I think we should now only accept it if they
5099 get it right (tridge) */
5100 if (!CAN_PRINT(conn)) {
5101 reply_doserror(req, ERRDOS, ERRnoaccess);
5102 END_PROFILE(SMBsplretq);
5106 reply_outbuf(req, 2, 3);
5107 SSVAL(req->outbuf,smb_vwv0,0);
5108 SSVAL(req->outbuf,smb_vwv1,0);
5109 SCVAL(smb_buf(req->outbuf),0,1);
5110 SSVAL(smb_buf(req->outbuf),1,0);
5112 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5113 start_index, max_count));
5116 print_queue_struct *queue = NULL;
5117 print_status_struct status;
5118 int count = print_queue_status(SNUM(conn), &queue, &status);
5119 int num_to_get = ABS(max_count);
5120 int first = (max_count>0?start_index:start_index+max_count+1);
5126 num_to_get = MIN(num_to_get,count-first);
5129 for (i=first;i<first+num_to_get;i++) {
5133 srv_put_dos_date2(p,0,queue[i].time);
5134 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5135 SSVAL(p,5, queue[i].job);
5136 SIVAL(p,7,queue[i].size);
5138 srvstr_push(blob, req->flags2, p+12,
5139 queue[i].fs_user, 16, STR_ASCII);
5141 if (message_push_blob(
5144 blob, sizeof(blob))) == -1) {
5145 reply_nterror(req, NT_STATUS_NO_MEMORY);
5146 END_PROFILE(SMBsplretq);
5152 SSVAL(req->outbuf,smb_vwv0,count);
5153 SSVAL(req->outbuf,smb_vwv1,
5154 (max_count>0?first+count:first-1));
5155 SCVAL(smb_buf(req->outbuf),0,1);
5156 SSVAL(smb_buf(req->outbuf),1,28*count);
5161 DEBUG(3,("%d entries returned in queue\n",count));
5164 END_PROFILE(SMBsplretq);
5168 /****************************************************************************
5169 Reply to a printwrite.
5170 ****************************************************************************/
5172 void reply_printwrite(struct smb_request *req)
5174 connection_struct *conn = req->conn;
5179 START_PROFILE(SMBsplwr);
5182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5183 END_PROFILE(SMBsplwr);
5187 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5189 if (!check_fsp(conn, req, fsp)) {
5190 END_PROFILE(SMBsplwr);
5194 if (!CAN_PRINT(conn)) {
5195 reply_doserror(req, ERRDOS, ERRnoaccess);
5196 END_PROFILE(SMBsplwr);
5200 if (!CHECK_WRITE(fsp)) {
5201 reply_doserror(req, ERRDOS, ERRbadaccess);
5202 END_PROFILE(SMBsplwr);
5206 numtowrite = SVAL(req->buf, 1);
5208 if (req->buflen < numtowrite + 3) {
5209 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5210 END_PROFILE(SMBsplwr);
5214 data = (const char *)req->buf + 3;
5216 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5217 reply_nterror(req, map_nt_error_from_unix(errno));
5218 END_PROFILE(SMBsplwr);
5222 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5224 END_PROFILE(SMBsplwr);
5228 /****************************************************************************
5230 ****************************************************************************/
5232 void reply_mkdir(struct smb_request *req)
5234 connection_struct *conn = req->conn;
5235 struct smb_filename *smb_dname = NULL;
5236 char *directory = NULL;
5238 TALLOC_CTX *ctx = talloc_tos();
5240 START_PROFILE(SMBmkdir);
5242 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5243 STR_TERMINATE, &status);
5244 if (!NT_STATUS_IS_OK(status)) {
5245 reply_nterror(req, status);
5249 status = filename_convert(ctx, conn,
5250 req->flags2 & FLAGS2_DFS_PATHNAMES,
5255 if (!NT_STATUS_IS_OK(status)) {
5256 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5257 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5258 ERRSRV, ERRbadpath);
5261 reply_nterror(req, status);
5265 status = create_directory(conn, req, smb_dname);
5267 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5269 if (!NT_STATUS_IS_OK(status)) {
5271 if (!use_nt_status()
5272 && NT_STATUS_EQUAL(status,
5273 NT_STATUS_OBJECT_NAME_COLLISION)) {
5275 * Yes, in the DOS error code case we get a
5276 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5277 * samba4 torture test.
5279 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5282 reply_nterror(req, status);
5286 reply_outbuf(req, 0, 0);
5288 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5290 TALLOC_FREE(smb_dname);
5291 END_PROFILE(SMBmkdir);
5295 /****************************************************************************
5296 Static function used by reply_rmdir to delete an entire directory
5297 tree recursively. Return True on ok, False on fail.
5298 ****************************************************************************/
5300 static bool recursive_rmdir(TALLOC_CTX *ctx,
5301 connection_struct *conn,
5302 struct smb_filename *smb_dname)
5308 struct smb_Dir *dir_hnd;
5310 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5312 dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0);
5316 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5317 struct smb_filename *smb_dname_full = NULL;
5318 char *fullname = NULL;
5319 bool do_break = true;
5322 if (ISDOT(dname) || ISDOTDOT(dname)) {
5327 if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
5333 /* Construct the full name. */
5334 fullname = talloc_asprintf(ctx,
5336 smb_dname->base_name,
5343 status = create_synthetic_smb_fname(talloc_tos(), fullname,
5346 if (!NT_STATUS_IS_OK(status)) {
5350 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5354 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5355 if(!recursive_rmdir(ctx, conn, smb_dname_full)) {
5358 if(SMB_VFS_RMDIR(conn,
5359 smb_dname_full->base_name) != 0) {
5362 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5366 /* Successful iteration. */
5370 TALLOC_FREE(smb_dname_full);
5371 TALLOC_FREE(fullname);
5378 TALLOC_FREE(dir_hnd);
5382 /****************************************************************************
5383 The internals of the rmdir code - called elsewhere.
5384 ****************************************************************************/
5386 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5387 connection_struct *conn,
5388 struct smb_filename *smb_dname)
5393 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5395 /* Might be a symlink. */
5396 if(SMB_VFS_LSTAT(conn, smb_dname) != 0) {
5397 return map_nt_error_from_unix(errno);
5400 if (S_ISLNK(smb_dname->st.st_ex_mode)) {
5401 /* Is what it points to a directory ? */
5402 if(SMB_VFS_STAT(conn, smb_dname) != 0) {
5403 return map_nt_error_from_unix(errno);
5405 if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
5406 return NT_STATUS_NOT_A_DIRECTORY;
5408 ret = SMB_VFS_UNLINK(conn, smb_dname);
5410 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5413 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5414 FILE_NOTIFY_CHANGE_DIR_NAME,
5415 smb_dname->base_name);
5416 return NT_STATUS_OK;
5419 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5421 * Check to see if the only thing in this directory are
5422 * vetoed files/directories. If so then delete them and
5423 * retry. If we fail to delete any of them (and we *don't*
5424 * do a recursive delete) then fail the rmdir.
5428 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5429 smb_dname->base_name, NULL,
5432 if(dir_hnd == NULL) {
5437 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5438 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) {
5442 if (!is_visible_file(conn, smb_dname->base_name, dname,
5447 if(!IS_VETO_PATH(conn, dname)) {
5448 TALLOC_FREE(dir_hnd);
5456 /* We only have veto files/directories.
5457 * Are we allowed to delete them ? */
5459 if(!lp_recursive_veto_delete(SNUM(conn))) {
5460 TALLOC_FREE(dir_hnd);
5465 /* Do a recursive delete. */
5466 RewindDir(dir_hnd,&dirpos);
5467 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5468 struct smb_filename *smb_dname_full = NULL;
5469 char *fullname = NULL;
5470 bool do_break = true;
5473 if (ISDOT(dname) || ISDOTDOT(dname)) {
5477 if (!is_visible_file(conn, smb_dname->base_name, dname,
5483 fullname = talloc_asprintf(ctx,
5485 smb_dname->base_name,
5493 status = create_synthetic_smb_fname(talloc_tos(),
5497 if (!NT_STATUS_IS_OK(status)) {
5498 errno = map_errno_from_nt_status(status);
5502 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5505 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5506 if(!recursive_rmdir(ctx, conn,
5510 if(SMB_VFS_RMDIR(conn,
5511 smb_dname_full->base_name) != 0) {
5514 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5518 /* Successful iteration. */
5522 TALLOC_FREE(fullname);
5523 TALLOC_FREE(smb_dname_full);
5528 TALLOC_FREE(dir_hnd);
5529 /* Retry the rmdir */
5530 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5536 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5537 "%s\n", smb_fname_str_dbg(smb_dname),
5539 return map_nt_error_from_unix(errno);
5542 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5543 FILE_NOTIFY_CHANGE_DIR_NAME,
5544 smb_dname->base_name);
5546 return NT_STATUS_OK;
5549 /****************************************************************************
5551 ****************************************************************************/
5553 void reply_rmdir(struct smb_request *req)
5555 connection_struct *conn = req->conn;
5556 struct smb_filename *smb_dname = NULL;
5557 char *directory = NULL;
5559 TALLOC_CTX *ctx = talloc_tos();
5560 struct smbd_server_connection *sconn = smbd_server_conn;
5562 START_PROFILE(SMBrmdir);
5564 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5565 STR_TERMINATE, &status);
5566 if (!NT_STATUS_IS_OK(status)) {
5567 reply_nterror(req, status);
5571 status = filename_convert(ctx, conn,
5572 req->flags2 & FLAGS2_DFS_PATHNAMES,
5577 if (!NT_STATUS_IS_OK(status)) {
5578 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5579 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5580 ERRSRV, ERRbadpath);
5583 reply_nterror(req, status);
5587 if (is_ntfs_stream_smb_fname(smb_dname)) {
5588 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5592 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5593 status = rmdir_internals(ctx, conn, smb_dname);
5594 if (!NT_STATUS_IS_OK(status)) {
5595 reply_nterror(req, status);
5599 reply_outbuf(req, 0, 0);
5601 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5603 TALLOC_FREE(smb_dname);
5604 END_PROFILE(SMBrmdir);
5608 /*******************************************************************
5609 Resolve wildcards in a filename rename.
5610 ********************************************************************/
5612 static bool resolve_wildcards(TALLOC_CTX *ctx,
5617 char *name2_copy = NULL;
5622 char *p,*p2, *pname1, *pname2;
5624 name2_copy = talloc_strdup(ctx, name2);
5629 pname1 = strrchr_m(name1,'/');
5630 pname2 = strrchr_m(name2_copy,'/');
5632 if (!pname1 || !pname2) {
5636 /* Truncate the copy of name2 at the last '/' */
5639 /* Now go past the '/' */
5643 root1 = talloc_strdup(ctx, pname1);
5644 root2 = talloc_strdup(ctx, pname2);
5646 if (!root1 || !root2) {
5650 p = strrchr_m(root1,'.');
5653 ext1 = talloc_strdup(ctx, p+1);
5655 ext1 = talloc_strdup(ctx, "");
5657 p = strrchr_m(root2,'.');
5660 ext2 = talloc_strdup(ctx, p+1);
5662 ext2 = talloc_strdup(ctx, "");
5665 if (!ext1 || !ext2) {
5673 /* Hmmm. Should this be mb-aware ? */
5676 } else if (*p2 == '*') {
5678 root2 = talloc_asprintf(ctx, "%s%s",
5697 /* Hmmm. Should this be mb-aware ? */
5700 } else if (*p2 == '*') {
5702 ext2 = talloc_asprintf(ctx, "%s%s",
5718 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5723 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5735 /****************************************************************************
5736 Ensure open files have their names updated. Updated to notify other smbd's
5738 ****************************************************************************/
5740 static void rename_open_files(connection_struct *conn,
5741 struct share_mode_lock *lck,
5742 const struct smb_filename *smb_fname_dst)
5745 bool did_rename = False;
5748 for(fsp = file_find_di_first(lck->id); fsp;
5749 fsp = file_find_di_next(fsp)) {
5750 /* fsp_name is a relative path under the fsp. To change this for other
5751 sharepaths we need to manipulate relative paths. */
5752 /* TODO - create the absolute path and manipulate the newname
5753 relative to the sharepath. */
5754 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5757 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5758 "(file_id %s) from %s -> %s\n", fsp->fnum,
5759 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5760 smb_fname_str_dbg(smb_fname_dst)));
5762 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5763 if (NT_STATUS_IS_OK(status)) {
5769 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5770 "for %s\n", file_id_string_tos(&lck->id),
5771 smb_fname_str_dbg(smb_fname_dst)));
5774 /* Send messages to all smbd's (not ourself) that the name has changed. */
5775 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5780 /****************************************************************************
5781 We need to check if the source path is a parent directory of the destination
5782 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5783 refuse the rename with a sharing violation. Under UNIX the above call can
5784 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5785 probably need to check that the client is a Windows one before disallowing
5786 this as a UNIX client (one with UNIX extensions) can know the source is a
5787 symlink and make this decision intelligently. Found by an excellent bug
5788 report from <AndyLiebman@aol.com>.
5789 ****************************************************************************/
5791 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5792 const struct smb_filename *smb_fname_dst)
5794 const char *psrc = smb_fname_src->base_name;
5795 const char *pdst = smb_fname_dst->base_name;
5798 if (psrc[0] == '.' && psrc[1] == '/') {
5801 if (pdst[0] == '.' && pdst[1] == '/') {
5804 if ((slen = strlen(psrc)) > strlen(pdst)) {
5807 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5811 * Do the notify calls from a rename
5814 static void notify_rename(connection_struct *conn, bool is_dir,
5815 const struct smb_filename *smb_fname_src,
5816 const struct smb_filename *smb_fname_dst)
5818 char *parent_dir_src = NULL;
5819 char *parent_dir_dst = NULL;
5822 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5823 : FILE_NOTIFY_CHANGE_FILE_NAME;
5825 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5826 &parent_dir_src, NULL) ||
5827 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5828 &parent_dir_dst, NULL)) {
5832 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5833 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5834 smb_fname_src->base_name);
5835 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5836 smb_fname_dst->base_name);
5839 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5840 smb_fname_src->base_name);
5841 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5842 smb_fname_dst->base_name);
5845 /* this is a strange one. w2k3 gives an additional event for
5846 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5847 files, but not directories */
5849 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5850 FILE_NOTIFY_CHANGE_ATTRIBUTES
5851 |FILE_NOTIFY_CHANGE_CREATION,
5852 smb_fname_dst->base_name);
5855 TALLOC_FREE(parent_dir_src);
5856 TALLOC_FREE(parent_dir_dst);
5859 /****************************************************************************
5860 Rename an open file - given an fsp.
5861 ****************************************************************************/
5863 NTSTATUS rename_internals_fsp(connection_struct *conn,
5865 const struct smb_filename *smb_fname_dst_in,
5867 bool replace_if_exists)
5869 TALLOC_CTX *ctx = talloc_tos();
5870 struct smb_filename *smb_fname_dst = NULL;
5871 NTSTATUS status = NT_STATUS_OK;
5872 struct share_mode_lock *lck = NULL;
5873 bool dst_exists, old_is_stream, new_is_stream;
5875 status = check_name(conn, smb_fname_dst_in->base_name);
5876 if (!NT_STATUS_IS_OK(status)) {
5880 /* Make a copy of the dst smb_fname structs */
5882 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5883 if (!NT_STATUS_IS_OK(status)) {
5887 /* Ensure the dst smb_fname contains a '/' */
5888 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5890 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5891 smb_fname_dst->base_name);
5893 status = NT_STATUS_NO_MEMORY;
5896 TALLOC_FREE(smb_fname_dst->base_name);
5897 smb_fname_dst->base_name = tmp;
5901 * Check for special case with case preserving and not
5902 * case sensitive. If the old last component differs from the original
5903 * last component only by case, then we should allow
5904 * the rename (user is trying to change the case of the
5907 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5908 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5909 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5911 char *fname_dst_lcomp_base_mod = NULL;
5912 struct smb_filename *smb_fname_orig_lcomp = NULL;
5915 * Get the last component of the destination name. Note that
5916 * we guarantee that destination name contains a '/' character
5919 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5920 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5921 if (!fname_dst_lcomp_base_mod) {
5922 status = NT_STATUS_NO_MEMORY;
5927 * Create an smb_filename struct using the original last
5928 * component of the destination.
5930 status = create_synthetic_smb_fname_split(ctx,
5931 smb_fname_dst->original_lcomp, NULL,
5932 &smb_fname_orig_lcomp);
5933 if (!NT_STATUS_IS_OK(status)) {
5934 TALLOC_FREE(fname_dst_lcomp_base_mod);
5938 /* If the base names only differ by case, use original. */
5939 if(!strcsequal(fname_dst_lcomp_base_mod,
5940 smb_fname_orig_lcomp->base_name)) {
5943 * Replace the modified last component with the
5946 *last_slash = '\0'; /* Truncate at the '/' */
5947 tmp = talloc_asprintf(smb_fname_dst,
5949 smb_fname_dst->base_name,
5950 smb_fname_orig_lcomp->base_name);
5952 status = NT_STATUS_NO_MEMORY;
5953 TALLOC_FREE(fname_dst_lcomp_base_mod);
5954 TALLOC_FREE(smb_fname_orig_lcomp);
5957 TALLOC_FREE(smb_fname_dst->base_name);
5958 smb_fname_dst->base_name = tmp;
5961 /* If the stream_names only differ by case, use original. */
5962 if(!strcsequal(smb_fname_dst->stream_name,
5963 smb_fname_orig_lcomp->stream_name)) {
5965 /* Use the original stream. */
5966 tmp = talloc_strdup(smb_fname_dst,
5967 smb_fname_orig_lcomp->stream_name);
5969 status = NT_STATUS_NO_MEMORY;
5970 TALLOC_FREE(fname_dst_lcomp_base_mod);
5971 TALLOC_FREE(smb_fname_orig_lcomp);
5974 TALLOC_FREE(smb_fname_dst->stream_name);
5975 smb_fname_dst->stream_name = tmp;
5977 TALLOC_FREE(fname_dst_lcomp_base_mod);
5978 TALLOC_FREE(smb_fname_orig_lcomp);
5982 * If the src and dest names are identical - including case,
5983 * don't do the rename, just return success.
5986 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5987 strcsequal(fsp->fsp_name->stream_name,
5988 smb_fname_dst->stream_name)) {
5989 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5990 "- returning success\n",
5991 smb_fname_str_dbg(smb_fname_dst)));
5992 status = NT_STATUS_OK;
5996 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
5997 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5999 /* Return the correct error code if both names aren't streams. */
6000 if (!old_is_stream && new_is_stream) {
6001 status = NT_STATUS_OBJECT_NAME_INVALID;
6005 if (old_is_stream && !new_is_stream) {
6006 status = NT_STATUS_INVALID_PARAMETER;
6010 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6012 if(!replace_if_exists && dst_exists) {
6013 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6014 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6015 smb_fname_str_dbg(smb_fname_dst)));
6016 status = NT_STATUS_OBJECT_NAME_COLLISION;
6021 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6022 &smb_fname_dst->st);
6023 files_struct *dst_fsp = file_find_di_first(fileid);
6024 /* The file can be open when renaming a stream */
6025 if (dst_fsp && !new_is_stream) {
6026 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6027 status = NT_STATUS_ACCESS_DENIED;
6032 /* Ensure we have a valid stat struct for the source. */
6033 status = vfs_stat_fsp(fsp);
6034 if (!NT_STATUS_IS_OK(status)) {
6038 status = can_rename(conn, fsp, attrs, &fsp->fsp_name->st);
6040 if (!NT_STATUS_IS_OK(status)) {
6041 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6042 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6043 smb_fname_str_dbg(smb_fname_dst)));
6044 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6045 status = NT_STATUS_ACCESS_DENIED;
6049 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6050 status = NT_STATUS_ACCESS_DENIED;
6053 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6057 * We have the file open ourselves, so not being able to get the
6058 * corresponding share mode lock is a fatal error.
6061 SMB_ASSERT(lck != NULL);
6063 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6064 uint32 create_options = fsp->fh->private_options;
6066 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6067 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6068 smb_fname_str_dbg(smb_fname_dst)));
6070 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6073 rename_open_files(conn, lck, smb_fname_dst);
6076 * A rename acts as a new file create w.r.t. allowing an initial delete
6077 * on close, probably because in Windows there is a new handle to the
6078 * new file. If initial delete on close was requested but not
6079 * originally set, we need to set it here. This is probably not 100% correct,
6080 * but will work for the CIFSFS client which in non-posix mode
6081 * depends on these semantics. JRA.
6084 if (create_options & FILE_DELETE_ON_CLOSE) {
6085 status = can_set_delete_on_close(fsp, True, 0);
6087 if (NT_STATUS_IS_OK(status)) {
6088 /* Note that here we set the *inital* delete on close flag,
6089 * not the regular one. The magic gets handled in close. */
6090 fsp->initial_delete_on_close = True;
6094 status = NT_STATUS_OK;
6100 if (errno == ENOTDIR || errno == EISDIR) {
6101 status = NT_STATUS_OBJECT_NAME_COLLISION;
6103 status = map_nt_error_from_unix(errno);
6106 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6107 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6108 smb_fname_str_dbg(smb_fname_dst)));
6111 TALLOC_FREE(smb_fname_dst);
6116 /****************************************************************************
6117 The guts of the rename command, split out so it may be called by the NT SMB
6119 ****************************************************************************/
6121 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6122 connection_struct *conn,
6123 struct smb_request *req,
6124 struct smb_filename *smb_fname_src,
6125 struct smb_filename *smb_fname_dst,
6127 bool replace_if_exists,
6130 uint32_t access_mask)
6132 char *fname_src_dir = NULL;
6133 char *fname_src_mask = NULL;
6135 NTSTATUS status = NT_STATUS_OK;
6136 struct smb_Dir *dir_hnd = NULL;
6139 int create_options = 0;
6140 bool posix_pathnames = lp_posix_pathnames();
6143 * Split the old name into directory and last component
6144 * strings. Note that unix_convert may have stripped off a
6145 * leading ./ from both name and newname if the rename is
6146 * at the root of the share. We need to make sure either both
6147 * name and newname contain a / character or neither of them do
6148 * as this is checked in resolve_wildcards().
6151 /* Split up the directory from the filename/mask. */
6152 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6153 &fname_src_dir, &fname_src_mask);
6154 if (!NT_STATUS_IS_OK(status)) {
6155 status = NT_STATUS_NO_MEMORY;
6160 * We should only check the mangled cache
6161 * here if unix_convert failed. This means
6162 * that the path in 'mask' doesn't exist
6163 * on the file system and so we need to look
6164 * for a possible mangle. This patch from
6165 * Tine Smukavec <valentin.smukavec@hermes.si>.
6168 if (!VALID_STAT(smb_fname_src->st) &&
6169 mangle_is_mangled(fname_src_mask, conn->params)) {
6170 char *new_mask = NULL;
6171 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6174 TALLOC_FREE(fname_src_mask);
6175 fname_src_mask = new_mask;
6179 if (!src_has_wild) {
6183 * Only one file needs to be renamed. Append the mask back
6184 * onto the directory.
6186 TALLOC_FREE(smb_fname_src->base_name);
6187 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6191 if (!smb_fname_src->base_name) {
6192 status = NT_STATUS_NO_MEMORY;
6196 /* Ensure dst fname contains a '/' also */
6197 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6199 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6200 smb_fname_dst->base_name);
6202 status = NT_STATUS_NO_MEMORY;
6205 TALLOC_FREE(smb_fname_dst->base_name);
6206 smb_fname_dst->base_name = tmp;
6209 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6210 "case_preserve = %d, short case preserve = %d, "
6211 "directory = %s, newname = %s, "
6212 "last_component_dest = %s\n",
6213 conn->case_sensitive, conn->case_preserve,
6214 conn->short_case_preserve,
6215 smb_fname_str_dbg(smb_fname_src),
6216 smb_fname_str_dbg(smb_fname_dst),
6217 smb_fname_dst->original_lcomp));
6219 /* The dest name still may have wildcards. */
6220 if (dest_has_wild) {
6221 char *fname_dst_mod = NULL;
6222 if (!resolve_wildcards(smb_fname_dst,
6223 smb_fname_src->base_name,
6224 smb_fname_dst->base_name,
6226 DEBUG(6, ("rename_internals: resolve_wildcards "
6228 smb_fname_src->base_name,
6229 smb_fname_dst->base_name));
6230 status = NT_STATUS_NO_MEMORY;
6233 TALLOC_FREE(smb_fname_dst->base_name);
6234 smb_fname_dst->base_name = fname_dst_mod;
6237 ZERO_STRUCT(smb_fname_src->st);
6238 if (posix_pathnames) {
6239 SMB_VFS_LSTAT(conn, smb_fname_src);
6241 SMB_VFS_STAT(conn, smb_fname_src);
6244 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6245 create_options |= FILE_DIRECTORY_FILE;
6248 status = SMB_VFS_CREATE_FILE(
6251 0, /* root_dir_fid */
6252 smb_fname_src, /* fname */
6253 access_mask, /* access_mask */
6254 (FILE_SHARE_READ | /* share_access */
6256 FILE_OPEN, /* create_disposition*/
6257 create_options, /* create_options */
6258 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6259 0, /* oplock_request */
6260 0, /* allocation_size */
6266 if (!NT_STATUS_IS_OK(status)) {
6267 DEBUG(3, ("Could not open rename source %s: %s\n",
6268 smb_fname_str_dbg(smb_fname_src),
6269 nt_errstr(status)));
6273 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6274 attrs, replace_if_exists);
6276 close_file(req, fsp, NORMAL_CLOSE);
6278 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6279 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6280 smb_fname_str_dbg(smb_fname_dst)));
6286 * Wildcards - process each file that matches.
6288 if (strequal(fname_src_mask, "????????.???")) {
6289 TALLOC_FREE(fname_src_mask);
6290 fname_src_mask = talloc_strdup(ctx, "*");
6291 if (!fname_src_mask) {
6292 status = NT_STATUS_NO_MEMORY;
6297 status = check_name(conn, fname_src_dir);
6298 if (!NT_STATUS_IS_OK(status)) {
6302 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6304 if (dir_hnd == NULL) {
6305 status = map_nt_error_from_unix(errno);
6309 status = NT_STATUS_NO_SUCH_FILE;
6311 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6312 * - gentest fix. JRA
6315 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
6316 files_struct *fsp = NULL;
6317 char *destname = NULL;
6318 bool sysdir_entry = False;
6320 /* Quick check for "." and ".." */
6321 if (ISDOT(dname) || ISDOTDOT(dname)) {
6323 sysdir_entry = True;
6330 if (!is_visible_file(conn, fname_src_dir, dname,
6331 &smb_fname_src->st, false)) {
6336 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6342 status = NT_STATUS_OBJECT_NAME_INVALID;
6346 TALLOC_FREE(smb_fname_src->base_name);
6347 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6351 if (!smb_fname_src->base_name) {
6352 status = NT_STATUS_NO_MEMORY;
6356 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6357 smb_fname_dst->base_name,
6359 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6360 smb_fname_src->base_name, destname));
6365 status = NT_STATUS_NO_MEMORY;
6369 TALLOC_FREE(smb_fname_dst->base_name);
6370 smb_fname_dst->base_name = destname;
6372 ZERO_STRUCT(smb_fname_src->st);
6373 if (posix_pathnames) {
6374 SMB_VFS_LSTAT(conn, smb_fname_src);
6376 SMB_VFS_STAT(conn, smb_fname_src);
6381 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6382 create_options |= FILE_DIRECTORY_FILE;
6385 status = SMB_VFS_CREATE_FILE(
6388 0, /* root_dir_fid */
6389 smb_fname_src, /* fname */
6390 access_mask, /* access_mask */
6391 (FILE_SHARE_READ | /* share_access */
6393 FILE_OPEN, /* create_disposition*/
6394 create_options, /* create_options */
6395 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6396 0, /* oplock_request */
6397 0, /* allocation_size */
6403 if (!NT_STATUS_IS_OK(status)) {
6404 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6405 "returned %s rename %s -> %s\n",
6407 smb_fname_str_dbg(smb_fname_src),
6408 smb_fname_str_dbg(smb_fname_dst)));
6412 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6414 if (!smb_fname_dst->original_lcomp) {
6415 status = NT_STATUS_NO_MEMORY;
6419 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6420 attrs, replace_if_exists);
6422 close_file(req, fsp, NORMAL_CLOSE);
6424 if (!NT_STATUS_IS_OK(status)) {
6425 DEBUG(3, ("rename_internals_fsp returned %s for "
6426 "rename %s -> %s\n", nt_errstr(status),
6427 smb_fname_str_dbg(smb_fname_src),
6428 smb_fname_str_dbg(smb_fname_dst)));
6434 DEBUG(3,("rename_internals: doing rename on %s -> "
6435 "%s\n", smb_fname_str_dbg(smb_fname_src),
6436 smb_fname_str_dbg(smb_fname_src)));
6439 TALLOC_FREE(dir_hnd);
6441 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6442 status = map_nt_error_from_unix(errno);
6447 TALLOC_FREE(fname_src_dir);
6448 TALLOC_FREE(fname_src_mask);
6452 /****************************************************************************
6454 ****************************************************************************/
6456 void reply_mv(struct smb_request *req)
6458 connection_struct *conn = req->conn;
6460 char *newname = NULL;
6464 bool src_has_wcard = False;
6465 bool dest_has_wcard = False;
6466 TALLOC_CTX *ctx = talloc_tos();
6467 struct smb_filename *smb_fname_src = NULL;
6468 struct smb_filename *smb_fname_dst = NULL;
6470 START_PROFILE(SMBmv);
6473 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6477 attrs = SVAL(req->vwv+0, 0);
6479 p = (const char *)req->buf + 1;
6480 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6481 &status, &src_has_wcard);
6482 if (!NT_STATUS_IS_OK(status)) {
6483 reply_nterror(req, status);
6487 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6488 &status, &dest_has_wcard);
6489 if (!NT_STATUS_IS_OK(status)) {
6490 reply_nterror(req, status);
6494 status = filename_convert(ctx,
6496 req->flags2 & FLAGS2_DFS_PATHNAMES,
6498 UCF_COND_ALLOW_WCARD_LCOMP,
6502 if (!NT_STATUS_IS_OK(status)) {
6503 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6504 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6505 ERRSRV, ERRbadpath);
6508 reply_nterror(req, status);
6512 status = filename_convert(ctx,
6514 req->flags2 & FLAGS2_DFS_PATHNAMES,
6516 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6520 if (!NT_STATUS_IS_OK(status)) {
6521 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6522 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6523 ERRSRV, ERRbadpath);
6526 reply_nterror(req, status);
6530 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6531 smb_fname_str_dbg(smb_fname_dst)));
6533 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6534 attrs, False, src_has_wcard, dest_has_wcard,
6536 if (!NT_STATUS_IS_OK(status)) {
6537 if (open_was_deferred(req->mid)) {
6538 /* We have re-scheduled this call. */
6541 reply_nterror(req, status);
6545 reply_outbuf(req, 0, 0);
6547 TALLOC_FREE(smb_fname_src);
6548 TALLOC_FREE(smb_fname_dst);
6553 /*******************************************************************
6554 Copy a file as part of a reply_copy.
6555 ******************************************************************/
6558 * TODO: check error codes on all callers
6561 NTSTATUS copy_file(TALLOC_CTX *ctx,
6562 connection_struct *conn,
6563 struct smb_filename *smb_fname_src,
6564 struct smb_filename *smb_fname_dst,
6567 bool target_is_directory)
6569 struct smb_filename *smb_fname_dst_tmp = NULL;
6571 files_struct *fsp1,*fsp2;
6573 uint32 new_create_disposition;
6577 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6578 if (!NT_STATUS_IS_OK(status)) {
6583 * If the target is a directory, extract the last component from the
6584 * src filename and append it to the dst filename
6586 if (target_is_directory) {
6589 /* dest/target can't be a stream if it's a directory. */
6590 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6592 p = strrchr_m(smb_fname_src->base_name,'/');
6596 p = smb_fname_src->base_name;
6598 smb_fname_dst_tmp->base_name =
6599 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6601 if (!smb_fname_dst_tmp->base_name) {
6602 status = NT_STATUS_NO_MEMORY;
6607 status = vfs_file_exist(conn, smb_fname_src);
6608 if (!NT_STATUS_IS_OK(status)) {
6612 if (!target_is_directory && count) {
6613 new_create_disposition = FILE_OPEN;
6615 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6617 &new_create_disposition,
6619 status = NT_STATUS_INVALID_PARAMETER;
6624 /* Open the src file for reading. */
6625 status = SMB_VFS_CREATE_FILE(
6628 0, /* root_dir_fid */
6629 smb_fname_src, /* fname */
6630 FILE_GENERIC_READ, /* access_mask */
6631 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6632 FILE_OPEN, /* create_disposition*/
6633 0, /* create_options */
6634 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6635 INTERNAL_OPEN_ONLY, /* oplock_request */
6636 0, /* allocation_size */
6642 if (!NT_STATUS_IS_OK(status)) {
6646 dosattrs = dos_mode(conn, smb_fname_src);
6648 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6649 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6652 /* Open the dst file for writing. */
6653 status = SMB_VFS_CREATE_FILE(
6656 0, /* root_dir_fid */
6657 smb_fname_dst, /* fname */
6658 FILE_GENERIC_WRITE, /* access_mask */
6659 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6660 new_create_disposition, /* create_disposition*/
6661 0, /* create_options */
6662 dosattrs, /* file_attributes */
6663 INTERNAL_OPEN_ONLY, /* oplock_request */
6664 0, /* allocation_size */
6670 if (!NT_STATUS_IS_OK(status)) {
6671 close_file(NULL, fsp1, ERROR_CLOSE);
6675 if ((ofun&3) == 1) {
6676 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6677 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6679 * Stop the copy from occurring.
6682 smb_fname_src->st.st_ex_size = 0;
6686 /* Do the actual copy. */
6687 if (smb_fname_src->st.st_ex_size) {
6688 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6691 close_file(NULL, fsp1, NORMAL_CLOSE);
6693 /* Ensure the modtime is set correctly on the destination file. */
6694 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6697 * As we are opening fsp1 read-only we only expect
6698 * an error on close on fsp2 if we are out of space.
6699 * Thus we don't look at the error return from the
6702 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6704 if (!NT_STATUS_IS_OK(status)) {
6708 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6709 status = NT_STATUS_DISK_FULL;
6713 status = NT_STATUS_OK;
6716 TALLOC_FREE(smb_fname_dst_tmp);
6720 /****************************************************************************
6721 Reply to a file copy.
6722 ****************************************************************************/
6724 void reply_copy(struct smb_request *req)
6726 connection_struct *conn = req->conn;
6727 struct smb_filename *smb_fname_src = NULL;
6728 struct smb_filename *smb_fname_dst = NULL;
6729 char *fname_src = NULL;
6730 char *fname_dst = NULL;
6731 char *fname_src_mask = NULL;
6732 char *fname_src_dir = NULL;
6735 int error = ERRnoaccess;
6739 bool target_is_directory=False;
6740 bool source_has_wild = False;
6741 bool dest_has_wild = False;
6743 TALLOC_CTX *ctx = talloc_tos();
6745 START_PROFILE(SMBcopy);
6748 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6752 tid2 = SVAL(req->vwv+0, 0);
6753 ofun = SVAL(req->vwv+1, 0);
6754 flags = SVAL(req->vwv+2, 0);
6756 p = (const char *)req->buf;
6757 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6758 &status, &source_has_wild);
6759 if (!NT_STATUS_IS_OK(status)) {
6760 reply_nterror(req, status);
6763 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6764 &status, &dest_has_wild);
6765 if (!NT_STATUS_IS_OK(status)) {
6766 reply_nterror(req, status);
6770 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6772 if (tid2 != conn->cnum) {
6773 /* can't currently handle inter share copies XXXX */
6774 DEBUG(3,("Rejecting inter-share copy\n"));
6775 reply_doserror(req, ERRSRV, ERRinvdevice);
6779 status = filename_convert(ctx, conn,
6780 req->flags2 & FLAGS2_DFS_PATHNAMES,
6782 UCF_COND_ALLOW_WCARD_LCOMP,
6785 if (!NT_STATUS_IS_OK(status)) {
6786 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6787 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6788 ERRSRV, ERRbadpath);
6791 reply_nterror(req, status);
6795 status = filename_convert(ctx, conn,
6796 req->flags2 & FLAGS2_DFS_PATHNAMES,
6798 UCF_COND_ALLOW_WCARD_LCOMP,
6801 if (!NT_STATUS_IS_OK(status)) {
6802 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6803 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6804 ERRSRV, ERRbadpath);
6807 reply_nterror(req, status);
6811 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6813 if ((flags&1) && target_is_directory) {
6814 reply_doserror(req, ERRDOS, ERRbadfile);
6818 if ((flags&2) && !target_is_directory) {
6819 reply_doserror(req, ERRDOS, ERRbadpath);
6823 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6824 /* wants a tree copy! XXXX */
6825 DEBUG(3,("Rejecting tree copy\n"));
6826 reply_doserror(req, ERRSRV, ERRerror);
6830 /* Split up the directory from the filename/mask. */
6831 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6832 &fname_src_dir, &fname_src_mask);
6833 if (!NT_STATUS_IS_OK(status)) {
6834 reply_nterror(req, NT_STATUS_NO_MEMORY);
6839 * We should only check the mangled cache
6840 * here if unix_convert failed. This means
6841 * that the path in 'mask' doesn't exist
6842 * on the file system and so we need to look
6843 * for a possible mangle. This patch from
6844 * Tine Smukavec <valentin.smukavec@hermes.si>.
6846 if (!VALID_STAT(smb_fname_src->st) &&
6847 mangle_is_mangled(fname_src_mask, conn->params)) {
6848 char *new_mask = NULL;
6849 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6850 &new_mask, conn->params);
6852 /* Use demangled name if one was successfully found. */
6854 TALLOC_FREE(fname_src_mask);
6855 fname_src_mask = new_mask;
6859 if (!source_has_wild) {
6862 * Only one file needs to be copied. Append the mask back onto
6865 TALLOC_FREE(smb_fname_src->base_name);
6866 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6870 if (!smb_fname_src->base_name) {
6871 reply_nterror(req, NT_STATUS_NO_MEMORY);
6875 if (dest_has_wild) {
6876 char *fname_dst_mod = NULL;
6877 if (!resolve_wildcards(smb_fname_dst,
6878 smb_fname_src->base_name,
6879 smb_fname_dst->base_name,
6881 reply_nterror(req, NT_STATUS_NO_MEMORY);
6884 TALLOC_FREE(smb_fname_dst->base_name);
6885 smb_fname_dst->base_name = fname_dst_mod;
6888 status = check_name(conn, smb_fname_src->base_name);
6889 if (!NT_STATUS_IS_OK(status)) {
6890 reply_nterror(req, status);
6894 status = check_name(conn, smb_fname_dst->base_name);
6895 if (!NT_STATUS_IS_OK(status)) {
6896 reply_nterror(req, status);
6900 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6901 ofun, count, target_is_directory);
6903 if(!NT_STATUS_IS_OK(status)) {
6904 reply_nterror(req, status);
6910 struct smb_Dir *dir_hnd = NULL;
6915 * There is a wildcard that requires us to actually read the
6916 * src dir and copy each file matching the mask to the dst.
6917 * Right now streams won't be copied, but this could
6918 * presumably be added with a nested loop for reach dir entry.
6920 SMB_ASSERT(!smb_fname_src->stream_name);
6921 SMB_ASSERT(!smb_fname_dst->stream_name);
6923 smb_fname_src->stream_name = NULL;
6924 smb_fname_dst->stream_name = NULL;
6926 if (strequal(fname_src_mask,"????????.???")) {
6927 TALLOC_FREE(fname_src_mask);
6928 fname_src_mask = talloc_strdup(ctx, "*");
6929 if (!fname_src_mask) {
6930 reply_nterror(req, NT_STATUS_NO_MEMORY);
6935 status = check_name(conn, fname_src_dir);
6936 if (!NT_STATUS_IS_OK(status)) {
6937 reply_nterror(req, status);
6941 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6942 if (dir_hnd == NULL) {
6943 status = map_nt_error_from_unix(errno);
6944 reply_nterror(req, status);
6950 /* Iterate over the src dir copying each entry to the dst. */
6951 while ((dname = ReadDirName(dir_hnd, &offset,
6952 &smb_fname_src->st))) {
6953 char *destname = NULL;
6955 if (ISDOT(dname) || ISDOTDOT(dname)) {
6960 if (!is_visible_file(conn, fname_src_dir, dname,
6961 &smb_fname_src->st, false)) {
6966 if(!mask_match(dname, fname_src_mask,
6967 conn->case_sensitive)) {
6972 error = ERRnoaccess;
6974 /* Get the src smb_fname struct setup. */
6975 TALLOC_FREE(smb_fname_src->base_name);
6976 smb_fname_src->base_name =
6977 talloc_asprintf(smb_fname_src, "%s/%s",
6978 fname_src_dir, dname);
6980 if (!smb_fname_src->base_name) {
6981 TALLOC_FREE(dir_hnd);
6983 reply_nterror(req, NT_STATUS_NO_MEMORY);
6987 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6988 smb_fname_dst->base_name,
6994 TALLOC_FREE(dir_hnd);
6996 reply_nterror(req, NT_STATUS_NO_MEMORY);
7000 TALLOC_FREE(smb_fname_dst->base_name);
7001 smb_fname_dst->base_name = destname;
7003 status = check_name(conn, smb_fname_src->base_name);
7004 if (!NT_STATUS_IS_OK(status)) {
7005 TALLOC_FREE(dir_hnd);
7007 reply_nterror(req, status);
7011 status = check_name(conn, smb_fname_dst->base_name);
7012 if (!NT_STATUS_IS_OK(status)) {
7013 TALLOC_FREE(dir_hnd);
7015 reply_nterror(req, status);
7019 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7020 smb_fname_src->base_name,
7021 smb_fname_dst->base_name));
7023 status = copy_file(ctx, conn, smb_fname_src,
7024 smb_fname_dst, ofun, count,
7025 target_is_directory);
7026 if (NT_STATUS_IS_OK(status)) {
7032 TALLOC_FREE(dir_hnd);
7036 reply_doserror(req, ERRDOS, error);
7040 reply_outbuf(req, 1, 0);
7041 SSVAL(req->outbuf,smb_vwv0,count);
7043 TALLOC_FREE(smb_fname_src);
7044 TALLOC_FREE(smb_fname_dst);
7045 TALLOC_FREE(fname_src);
7046 TALLOC_FREE(fname_dst);
7047 TALLOC_FREE(fname_src_mask);
7048 TALLOC_FREE(fname_src_dir);
7050 END_PROFILE(SMBcopy);
7055 #define DBGC_CLASS DBGC_LOCKING
7057 /****************************************************************************
7058 Get a lock pid, dealing with large count requests.
7059 ****************************************************************************/
7061 uint32 get_lock_pid(const uint8_t *data, int data_offset,
7062 bool large_file_format)
7064 if(!large_file_format)
7065 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
7067 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7070 /****************************************************************************
7071 Get a lock count, dealing with large count requests.
7072 ****************************************************************************/
7074 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7075 bool large_file_format)
7079 if(!large_file_format) {
7080 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7083 #if defined(HAVE_LONGLONG)
7084 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7085 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7086 #else /* HAVE_LONGLONG */
7089 * NT4.x seems to be broken in that it sends large file (64 bit)
7090 * lockingX calls even if the CAP_LARGE_FILES was *not*
7091 * negotiated. For boxes without large unsigned ints truncate the
7092 * lock count by dropping the top 32 bits.
7095 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7096 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7097 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7098 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7099 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7102 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7103 #endif /* HAVE_LONGLONG */
7109 #if !defined(HAVE_LONGLONG)
7110 /****************************************************************************
7111 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7112 ****************************************************************************/
7114 static uint32 map_lock_offset(uint32 high, uint32 low)
7118 uint32 highcopy = high;
7121 * Try and find out how many significant bits there are in high.
7124 for(i = 0; highcopy; i++)
7128 * We use 31 bits not 32 here as POSIX
7129 * lock offsets may not be negative.
7132 mask = (~0) << (31 - i);
7135 return 0; /* Fail. */
7141 #endif /* !defined(HAVE_LONGLONG) */
7143 /****************************************************************************
7144 Get a lock offset, dealing with large offset requests.
7145 ****************************************************************************/
7147 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7148 bool large_file_format, bool *err)
7150 uint64_t offset = 0;
7154 if(!large_file_format) {
7155 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7158 #if defined(HAVE_LONGLONG)
7159 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7160 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7161 #else /* HAVE_LONGLONG */
7164 * NT4.x seems to be broken in that it sends large file (64 bit)
7165 * lockingX calls even if the CAP_LARGE_FILES was *not*
7166 * negotiated. For boxes without large unsigned ints mangle the
7167 * lock offset by mapping the top 32 bits onto the lower 32.
7170 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7171 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7172 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7175 if((new_low = map_lock_offset(high, low)) == 0) {
7177 return (uint64_t)-1;
7180 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7181 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7182 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7183 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7186 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7187 #endif /* HAVE_LONGLONG */
7193 NTSTATUS smbd_do_locking(struct smb_request *req,
7197 uint16_t num_ulocks,
7198 struct smbd_lock_element *ulocks,
7200 struct smbd_lock_element *locks,
7203 connection_struct *conn = req->conn;
7205 NTSTATUS status = NT_STATUS_OK;
7209 /* Data now points at the beginning of the list
7210 of smb_unlkrng structs */
7211 for(i = 0; i < (int)num_ulocks; i++) {
7212 struct smbd_lock_element *e = &ulocks[i];
7214 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7215 "pid %u, file %s\n",
7218 (unsigned int)e->smbpid,
7221 if (e->brltype != UNLOCK_LOCK) {
7222 /* this can only happen with SMB2 */
7223 return NT_STATUS_INVALID_PARAMETER;
7226 status = do_unlock(smbd_messaging_context(),
7233 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7234 nt_errstr(status)));
7236 if (!NT_STATUS_IS_OK(status)) {
7241 /* Setup the timeout in seconds. */
7243 if (!lp_blocking_locks(SNUM(conn))) {
7247 /* Data now points at the beginning of the list
7248 of smb_lkrng structs */
7250 for(i = 0; i < (int)num_locks; i++) {
7251 struct smbd_lock_element *e = &locks[i];
7253 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for pid "
7254 "%u, file %s timeout = %d\n",
7257 (unsigned int)e->smbpid,
7261 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7262 struct blocking_lock_record *blr = NULL;
7264 if (lp_blocking_locks(SNUM(conn))) {
7266 /* Schedule a message to ourselves to
7267 remove the blocking lock record and
7268 return the right error. */
7270 blr = blocking_lock_cancel(fsp,
7276 NT_STATUS_FILE_LOCK_CONFLICT);
7278 return NT_STATUS_DOS(
7280 ERRcancelviolation);
7283 /* Remove a matching pending lock. */
7284 status = do_lock_cancel(fsp,
7291 bool blocking_lock = timeout ? true : false;
7292 bool defer_lock = false;
7293 struct byte_range_lock *br_lck;
7294 uint32_t block_smbpid;
7296 br_lck = do_lock(smbd_messaging_context(),
7308 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7309 /* Windows internal resolution for blocking locks seems
7310 to be about 200ms... Don't wait for less than that. JRA. */
7311 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7312 timeout = lp_lock_spin_time();
7317 /* This heuristic seems to match W2K3 very well. If a
7318 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7319 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7320 far as I can tell. Replacement for do_lock_spin(). JRA. */
7322 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7323 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7325 timeout = lp_lock_spin_time();
7328 if (br_lck && defer_lock) {
7330 * A blocking lock was requested. Package up
7331 * this smb into a queued request and push it
7332 * onto the blocking lock queue.
7334 if(push_blocking_lock_request(br_lck,
7345 TALLOC_FREE(br_lck);
7347 return NT_STATUS_OK;
7351 TALLOC_FREE(br_lck);
7354 if (!NT_STATUS_IS_OK(status)) {
7359 /* If any of the above locks failed, then we must unlock
7360 all of the previous locks (X/Open spec). */
7362 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7364 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7365 i = -1; /* we want to skip the for loop */
7369 * Ensure we don't do a remove on the lock that just failed,
7370 * as under POSIX rules, if we have a lock already there, we
7371 * will delete it (and we shouldn't) .....
7373 for(i--; i >= 0; i--) {
7374 struct smbd_lock_element *e = &locks[i];
7376 do_unlock(smbd_messaging_context(),
7386 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7387 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7389 return NT_STATUS_OK;
7392 /****************************************************************************
7393 Reply to a lockingX request.
7394 ****************************************************************************/
7396 void reply_lockingX(struct smb_request *req)
7398 connection_struct *conn = req->conn;
7400 unsigned char locktype;
7401 unsigned char oplocklevel;
7406 const uint8_t *data;
7407 bool large_file_format;
7409 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7410 struct smbd_lock_element *ulocks;
7411 struct smbd_lock_element *locks;
7414 START_PROFILE(SMBlockingX);
7417 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7418 END_PROFILE(SMBlockingX);
7422 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7423 locktype = CVAL(req->vwv+3, 0);
7424 oplocklevel = CVAL(req->vwv+3, 1);
7425 num_ulocks = SVAL(req->vwv+6, 0);
7426 num_locks = SVAL(req->vwv+7, 0);
7427 lock_timeout = IVAL(req->vwv+4, 0);
7428 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7430 if (!check_fsp(conn, req, fsp)) {
7431 END_PROFILE(SMBlockingX);
7437 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7438 /* we don't support these - and CANCEL_LOCK makes w2k
7439 and XP reboot so I don't really want to be
7440 compatible! (tridge) */
7441 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7442 END_PROFILE(SMBlockingX);
7446 /* Check if this is an oplock break on a file
7447 we have granted an oplock on.
7449 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7450 /* Client can insist on breaking to none. */
7451 bool break_to_none = (oplocklevel == 0);
7454 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7455 "for fnum = %d\n", (unsigned int)oplocklevel,
7459 * Make sure we have granted an exclusive or batch oplock on
7463 if (fsp->oplock_type == 0) {
7465 /* The Samba4 nbench simulator doesn't understand
7466 the difference between break to level2 and break
7467 to none from level2 - it sends oplock break
7468 replies in both cases. Don't keep logging an error
7469 message here - just ignore it. JRA. */
7471 DEBUG(5,("reply_lockingX: Error : oplock break from "
7472 "client for fnum = %d (oplock=%d) and no "
7473 "oplock granted on this file (%s).\n",
7474 fsp->fnum, fsp->oplock_type,
7477 /* if this is a pure oplock break request then don't
7479 if (num_locks == 0 && num_ulocks == 0) {
7480 END_PROFILE(SMBlockingX);
7483 END_PROFILE(SMBlockingX);
7484 reply_doserror(req, ERRDOS, ERRlock);
7489 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7491 result = remove_oplock(fsp);
7493 result = downgrade_oplock(fsp);
7497 DEBUG(0, ("reply_lockingX: error in removing "
7498 "oplock on file %s\n", fsp_str_dbg(fsp)));
7499 /* Hmmm. Is this panic justified? */
7500 smb_panic("internal tdb error");
7503 reply_to_oplock_break_requests(fsp);
7505 /* if this is a pure oplock break request then don't send a
7507 if (num_locks == 0 && num_ulocks == 0) {
7508 /* Sanity check - ensure a pure oplock break is not a
7510 if(CVAL(req->vwv+0, 0) != 0xff)
7511 DEBUG(0,("reply_lockingX: Error : pure oplock "
7512 "break is a chained %d request !\n",
7513 (unsigned int)CVAL(req->vwv+0, 0)));
7514 END_PROFILE(SMBlockingX);
7520 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7521 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7522 END_PROFILE(SMBlockingX);
7526 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7527 if (ulocks == NULL) {
7528 reply_nterror(req, NT_STATUS_NO_MEMORY);
7529 END_PROFILE(SMBlockingX);
7533 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7534 if (locks == NULL) {
7535 reply_nterror(req, NT_STATUS_NO_MEMORY);
7536 END_PROFILE(SMBlockingX);
7540 /* Data now points at the beginning of the list
7541 of smb_unlkrng structs */
7542 for(i = 0; i < (int)num_ulocks; i++) {
7543 ulocks[i].smbpid = get_lock_pid(data, i, large_file_format);
7544 ulocks[i].count = get_lock_count(data, i, large_file_format);
7545 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7546 ulocks[i].brltype = UNLOCK_LOCK;
7549 * There is no error code marked "stupid client bug".... :-).
7552 END_PROFILE(SMBlockingX);
7553 reply_doserror(req, ERRDOS, ERRnoaccess);
7558 /* Now do any requested locks */
7559 data += ((large_file_format ? 20 : 10)*num_ulocks);
7561 /* Data now points at the beginning of the list
7562 of smb_lkrng structs */
7564 for(i = 0; i < (int)num_locks; i++) {
7565 locks[i].smbpid = get_lock_pid(data, i, large_file_format);
7566 locks[i].count = get_lock_count(data, i, large_file_format);
7567 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7569 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7570 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7571 locks[i].brltype = PENDING_READ_LOCK;
7573 locks[i].brltype = READ_LOCK;
7576 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7577 locks[i].brltype = PENDING_WRITE_LOCK;
7579 locks[i].brltype = WRITE_LOCK;
7584 * There is no error code marked "stupid client bug".... :-).
7587 END_PROFILE(SMBlockingX);
7588 reply_doserror(req, ERRDOS, ERRnoaccess);
7593 status = smbd_do_locking(req, fsp,
7594 locktype, lock_timeout,
7598 if (!NT_STATUS_IS_OK(status)) {
7599 END_PROFILE(SMBlockingX);
7600 reply_nterror(req, status);
7604 END_PROFILE(SMBlockingX);
7608 reply_outbuf(req, 2, 0);
7610 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7611 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7613 END_PROFILE(SMBlockingX);
7618 #define DBGC_CLASS DBGC_ALL
7620 /****************************************************************************
7621 Reply to a SMBreadbmpx (read block multiplex) request.
7622 Always reply with an error, if someone has a platform really needs this,
7623 please contact vl@samba.org
7624 ****************************************************************************/
7626 void reply_readbmpx(struct smb_request *req)
7628 START_PROFILE(SMBreadBmpx);
7629 reply_doserror(req, ERRSRV, ERRuseSTD);
7630 END_PROFILE(SMBreadBmpx);
7634 /****************************************************************************
7635 Reply to a SMBreadbs (read block multiplex secondary) request.
7636 Always reply with an error, if someone has a platform really needs this,
7637 please contact vl@samba.org
7638 ****************************************************************************/
7640 void reply_readbs(struct smb_request *req)
7642 START_PROFILE(SMBreadBs);
7643 reply_doserror(req, ERRSRV, ERRuseSTD);
7644 END_PROFILE(SMBreadBs);
7648 /****************************************************************************
7649 Reply to a SMBsetattrE.
7650 ****************************************************************************/
7652 void reply_setattrE(struct smb_request *req)
7654 connection_struct *conn = req->conn;
7655 struct smb_file_time ft;
7659 START_PROFILE(SMBsetattrE);
7663 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7667 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7669 if(!fsp || (fsp->conn != conn)) {
7670 reply_doserror(req, ERRDOS, ERRbadfid);
7675 * Convert the DOS times into unix times.
7678 ft.atime = convert_time_t_to_timespec(
7679 srv_make_unix_date2(req->vwv+3));
7680 ft.mtime = convert_time_t_to_timespec(
7681 srv_make_unix_date2(req->vwv+5));
7682 ft.create_time = convert_time_t_to_timespec(
7683 srv_make_unix_date2(req->vwv+1));
7685 reply_outbuf(req, 0, 0);
7688 * Patch from Ray Frush <frush@engr.colostate.edu>
7689 * Sometimes times are sent as zero - ignore them.
7692 /* Ensure we have a valid stat struct for the source. */
7693 status = vfs_stat_fsp(fsp);
7694 if (!NT_STATUS_IS_OK(status)) {
7695 reply_nterror(req, status);
7699 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7700 if (!NT_STATUS_IS_OK(status)) {
7701 reply_doserror(req, ERRDOS, ERRnoaccess);
7705 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7708 (unsigned int)ft.atime.tv_sec,
7709 (unsigned int)ft.mtime.tv_sec,
7710 (unsigned int)ft.create_time.tv_sec
7713 END_PROFILE(SMBsetattrE);
7718 /* Back from the dead for OS/2..... JRA. */
7720 /****************************************************************************
7721 Reply to a SMBwritebmpx (write block multiplex primary) request.
7722 Always reply with an error, if someone has a platform really needs this,
7723 please contact vl@samba.org
7724 ****************************************************************************/
7726 void reply_writebmpx(struct smb_request *req)
7728 START_PROFILE(SMBwriteBmpx);
7729 reply_doserror(req, ERRSRV, ERRuseSTD);
7730 END_PROFILE(SMBwriteBmpx);
7734 /****************************************************************************
7735 Reply to a SMBwritebs (write block multiplex secondary) request.
7736 Always reply with an error, if someone has a platform really needs this,
7737 please contact vl@samba.org
7738 ****************************************************************************/
7740 void reply_writebs(struct smb_request *req)
7742 START_PROFILE(SMBwriteBs);
7743 reply_doserror(req, ERRSRV, ERRuseSTD);
7744 END_PROFILE(SMBwriteBs);
7748 /****************************************************************************
7749 Reply to a SMBgetattrE.
7750 ****************************************************************************/
7752 void reply_getattrE(struct smb_request *req)
7754 connection_struct *conn = req->conn;
7757 struct timespec create_ts;
7759 START_PROFILE(SMBgetattrE);
7762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7763 END_PROFILE(SMBgetattrE);
7767 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7769 if(!fsp || (fsp->conn != conn)) {
7770 reply_doserror(req, ERRDOS, ERRbadfid);
7771 END_PROFILE(SMBgetattrE);
7775 /* Do an fstat on this file */
7777 reply_nterror(req, map_nt_error_from_unix(errno));
7778 END_PROFILE(SMBgetattrE);
7782 mode = dos_mode(conn, fsp->fsp_name);
7785 * Convert the times into dos times. Set create
7786 * date to be last modify date as UNIX doesn't save
7790 reply_outbuf(req, 11, 0);
7792 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7793 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7794 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7795 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7796 /* Should we check pending modtime here ? JRA */
7797 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7798 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7801 SIVAL(req->outbuf, smb_vwv6, 0);
7802 SIVAL(req->outbuf, smb_vwv8, 0);
7804 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7805 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7806 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7808 SSVAL(req->outbuf,smb_vwv10, mode);
7810 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7812 END_PROFILE(SMBgetattrE);