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 ((*s == ':') && !posix_path && !stream_started) {
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 = req->sconn;
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 = req->sconn;
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_force_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_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
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_force_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_force_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_nterror(req, NT_STATUS_INVALID_HANDLE);
924 END_PROFILE(SMBioctl);
928 if (fsp->print_file) {
929 SSVAL(p, 0, fsp->print_file->rap_jobid);
933 srvstr_push((char *)req->outbuf, req->flags2, p+2,
935 STR_TERMINATE|STR_ASCII);
937 srvstr_push((char *)req->outbuf, req->flags2,
938 p+18, lp_servicename(SNUM(conn)),
939 13, STR_TERMINATE|STR_ASCII);
947 END_PROFILE(SMBioctl);
951 /****************************************************************************
952 Strange checkpath NTSTATUS mapping.
953 ****************************************************************************/
955 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
957 /* Strange DOS error code semantics only for checkpath... */
958 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
959 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
960 /* We need to map to ERRbadpath */
961 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
967 /****************************************************************************
968 Reply to a checkpath.
969 ****************************************************************************/
971 void reply_checkpath(struct smb_request *req)
973 connection_struct *conn = req->conn;
974 struct smb_filename *smb_fname = NULL;
977 TALLOC_CTX *ctx = talloc_tos();
979 START_PROFILE(SMBcheckpath);
981 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
982 STR_TERMINATE, &status);
984 if (!NT_STATUS_IS_OK(status)) {
985 status = map_checkpath_error(req->flags2, status);
986 reply_nterror(req, status);
987 END_PROFILE(SMBcheckpath);
991 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
993 status = filename_convert(ctx,
995 req->flags2 & FLAGS2_DFS_PATHNAMES,
1001 if (!NT_STATUS_IS_OK(status)) {
1002 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1003 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1004 ERRSRV, ERRbadpath);
1005 END_PROFILE(SMBcheckpath);
1011 if (!VALID_STAT(smb_fname->st) &&
1012 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1013 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1014 smb_fname_str_dbg(smb_fname), strerror(errno)));
1015 status = map_nt_error_from_unix(errno);
1019 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1020 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1021 ERRDOS, ERRbadpath);
1025 reply_outbuf(req, 0, 0);
1028 /* We special case this - as when a Windows machine
1029 is parsing a path is steps through the components
1030 one at a time - if a component fails it expects
1031 ERRbadpath, not ERRbadfile.
1033 status = map_checkpath_error(req->flags2, status);
1034 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1036 * Windows returns different error codes if
1037 * the parent directory is valid but not the
1038 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1039 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1040 * if the path is invalid.
1042 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1043 ERRDOS, ERRbadpath);
1047 reply_nterror(req, status);
1050 TALLOC_FREE(smb_fname);
1051 END_PROFILE(SMBcheckpath);
1055 /****************************************************************************
1057 ****************************************************************************/
1059 void reply_getatr(struct smb_request *req)
1061 connection_struct *conn = req->conn;
1062 struct smb_filename *smb_fname = NULL;
1069 TALLOC_CTX *ctx = talloc_tos();
1070 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1072 START_PROFILE(SMBgetatr);
1074 p = (const char *)req->buf + 1;
1075 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1076 if (!NT_STATUS_IS_OK(status)) {
1077 reply_nterror(req, status);
1081 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1082 under WfWg - weird! */
1083 if (*fname == '\0') {
1084 mode = aHIDDEN | aDIR;
1085 if (!CAN_WRITE(conn)) {
1091 status = filename_convert(ctx,
1093 req->flags2 & FLAGS2_DFS_PATHNAMES,
1098 if (!NT_STATUS_IS_OK(status)) {
1099 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1100 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1101 ERRSRV, ERRbadpath);
1104 reply_nterror(req, status);
1107 if (!VALID_STAT(smb_fname->st) &&
1108 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1109 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1110 smb_fname_str_dbg(smb_fname),
1112 reply_nterror(req, map_nt_error_from_unix(errno));
1116 mode = dos_mode(conn, smb_fname);
1117 size = smb_fname->st.st_ex_size;
1119 if (ask_sharemode) {
1120 struct timespec write_time_ts;
1121 struct file_id fileid;
1123 ZERO_STRUCT(write_time_ts);
1124 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1125 get_file_infos(fileid, NULL, &write_time_ts);
1126 if (!null_timespec(write_time_ts)) {
1127 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1131 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1137 reply_outbuf(req, 10, 0);
1139 SSVAL(req->outbuf,smb_vwv0,mode);
1140 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1141 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1143 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1145 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1147 if (get_Protocol() >= PROTOCOL_NT1) {
1148 SSVAL(req->outbuf, smb_flg2,
1149 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1152 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1153 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1156 TALLOC_FREE(smb_fname);
1158 END_PROFILE(SMBgetatr);
1162 /****************************************************************************
1164 ****************************************************************************/
1166 void reply_setatr(struct smb_request *req)
1168 struct smb_file_time ft;
1169 connection_struct *conn = req->conn;
1170 struct smb_filename *smb_fname = NULL;
1176 TALLOC_CTX *ctx = talloc_tos();
1178 START_PROFILE(SMBsetatr);
1183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1187 p = (const char *)req->buf + 1;
1188 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1189 if (!NT_STATUS_IS_OK(status)) {
1190 reply_nterror(req, status);
1194 status = filename_convert(ctx,
1196 req->flags2 & FLAGS2_DFS_PATHNAMES,
1201 if (!NT_STATUS_IS_OK(status)) {
1202 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1203 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1204 ERRSRV, ERRbadpath);
1207 reply_nterror(req, status);
1211 if (smb_fname->base_name[0] == '.' &&
1212 smb_fname->base_name[1] == '\0') {
1214 * Not sure here is the right place to catch this
1215 * condition. Might be moved to somewhere else later -- vl
1217 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1221 mode = SVAL(req->vwv+0, 0);
1222 mtime = srv_make_unix_date3(req->vwv+1);
1224 ft.mtime = convert_time_t_to_timespec(mtime);
1225 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1226 if (!NT_STATUS_IS_OK(status)) {
1227 reply_nterror(req, status);
1231 if (mode != FILE_ATTRIBUTE_NORMAL) {
1232 if (VALID_STAT_OF_DIR(smb_fname->st))
1237 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1239 reply_nterror(req, map_nt_error_from_unix(errno));
1244 reply_outbuf(req, 0, 0);
1246 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1249 TALLOC_FREE(smb_fname);
1250 END_PROFILE(SMBsetatr);
1254 /****************************************************************************
1256 ****************************************************************************/
1258 void reply_dskattr(struct smb_request *req)
1260 connection_struct *conn = req->conn;
1261 uint64_t dfree,dsize,bsize;
1262 START_PROFILE(SMBdskattr);
1264 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1265 reply_nterror(req, map_nt_error_from_unix(errno));
1266 END_PROFILE(SMBdskattr);
1270 reply_outbuf(req, 5, 0);
1272 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1273 double total_space, free_space;
1274 /* we need to scale this to a number that DOS6 can handle. We
1275 use floating point so we can handle large drives on systems
1276 that don't have 64 bit integers
1278 we end up displaying a maximum of 2G to DOS systems
1280 total_space = dsize * (double)bsize;
1281 free_space = dfree * (double)bsize;
1283 dsize = (uint64_t)((total_space+63*512) / (64*512));
1284 dfree = (uint64_t)((free_space+63*512) / (64*512));
1286 if (dsize > 0xFFFF) dsize = 0xFFFF;
1287 if (dfree > 0xFFFF) dfree = 0xFFFF;
1289 SSVAL(req->outbuf,smb_vwv0,dsize);
1290 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1291 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1292 SSVAL(req->outbuf,smb_vwv3,dfree);
1294 SSVAL(req->outbuf,smb_vwv0,dsize);
1295 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1296 SSVAL(req->outbuf,smb_vwv2,512);
1297 SSVAL(req->outbuf,smb_vwv3,dfree);
1300 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1302 END_PROFILE(SMBdskattr);
1307 * Utility function to split the filename from the directory.
1309 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1310 char **fname_dir_out,
1311 char **fname_mask_out)
1313 const char *p = NULL;
1314 char *fname_dir = NULL;
1315 char *fname_mask = NULL;
1317 p = strrchr_m(fname_in, '/');
1319 fname_dir = talloc_strdup(ctx, ".");
1320 fname_mask = talloc_strdup(ctx, fname_in);
1322 fname_dir = talloc_strndup(ctx, fname_in,
1323 PTR_DIFF(p, fname_in));
1324 fname_mask = talloc_strdup(ctx, p+1);
1327 if (!fname_dir || !fname_mask) {
1328 TALLOC_FREE(fname_dir);
1329 TALLOC_FREE(fname_mask);
1330 return NT_STATUS_NO_MEMORY;
1333 *fname_dir_out = fname_dir;
1334 *fname_mask_out = fname_mask;
1335 return NT_STATUS_OK;
1338 /****************************************************************************
1340 Can be called from SMBsearch, SMBffirst or SMBfunique.
1341 ****************************************************************************/
1343 void reply_search(struct smb_request *req)
1345 connection_struct *conn = req->conn;
1347 const char *mask = NULL;
1348 char *directory = NULL;
1349 struct smb_filename *smb_fname = NULL;
1353 struct timespec date;
1355 unsigned int numentries = 0;
1356 unsigned int maxentries = 0;
1357 bool finished = False;
1362 bool check_descend = False;
1363 bool expect_close = False;
1365 bool mask_contains_wcard = False;
1366 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1367 TALLOC_CTX *ctx = talloc_tos();
1368 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1369 struct dptr_struct *dirptr = NULL;
1370 struct smbd_server_connection *sconn = req->sconn;
1372 START_PROFILE(SMBsearch);
1375 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1379 if (lp_posix_pathnames()) {
1380 reply_unknown_new(req, req->cmd);
1384 /* If we were called as SMBffirst then we must expect close. */
1385 if(req->cmd == SMBffirst) {
1386 expect_close = True;
1389 reply_outbuf(req, 1, 3);
1390 maxentries = SVAL(req->vwv+0, 0);
1391 dirtype = SVAL(req->vwv+1, 0);
1392 p = (const char *)req->buf + 1;
1393 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1394 &nt_status, &mask_contains_wcard);
1395 if (!NT_STATUS_IS_OK(nt_status)) {
1396 reply_nterror(req, nt_status);
1401 status_len = SVAL(p, 0);
1404 /* dirtype &= ~aDIR; */
1406 if (status_len == 0) {
1407 nt_status = filename_convert(ctx, conn,
1408 req->flags2 & FLAGS2_DFS_PATHNAMES,
1410 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1411 &mask_contains_wcard,
1413 if (!NT_STATUS_IS_OK(nt_status)) {
1414 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1415 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1416 ERRSRV, ERRbadpath);
1419 reply_nterror(req, nt_status);
1423 directory = smb_fname->base_name;
1425 p = strrchr_m(directory,'/');
1426 if ((p != NULL) && (*directory != '/')) {
1428 directory = talloc_strndup(ctx, directory,
1429 PTR_DIFF(p, directory));
1432 directory = talloc_strdup(ctx,".");
1436 reply_nterror(req, NT_STATUS_NO_MEMORY);
1440 memset((char *)status,'\0',21);
1441 SCVAL(status,0,(dirtype & 0x1F));
1443 nt_status = dptr_create(conn,
1449 mask_contains_wcard,
1452 if (!NT_STATUS_IS_OK(nt_status)) {
1453 reply_nterror(req, nt_status);
1456 dptr_num = dptr_dnum(dirptr);
1459 const char *dirpath;
1461 memcpy(status,p,21);
1462 status_dirtype = CVAL(status,0) & 0x1F;
1463 if (status_dirtype != (dirtype & 0x1F)) {
1464 dirtype = status_dirtype;
1467 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1471 dirpath = dptr_path(sconn, dptr_num);
1472 directory = talloc_strdup(ctx, dirpath);
1474 reply_nterror(req, NT_STATUS_NO_MEMORY);
1478 mask = dptr_wcard(sconn, dptr_num);
1483 * For a 'continue' search we have no string. So
1484 * check from the initial saved string.
1486 mask_contains_wcard = ms_has_wild(mask);
1487 dirtype = dptr_attr(sconn, dptr_num);
1490 DEBUG(4,("dptr_num is %d\n",dptr_num));
1492 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1493 dptr_init_search_op(dirptr);
1495 if ((dirtype&0x1F) == aVOLID) {
1496 char buf[DIR_STRUCT_SIZE];
1497 memcpy(buf,status,21);
1498 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1499 0,aVOLID,0,!allow_long_path_components)) {
1500 reply_nterror(req, NT_STATUS_NO_MEMORY);
1503 dptr_fill(sconn, buf+12,dptr_num);
1504 if (dptr_zero(buf+12) && (status_len==0)) {
1509 if (message_push_blob(&req->outbuf,
1510 data_blob_const(buf, sizeof(buf)))
1512 reply_nterror(req, NT_STATUS_NO_MEMORY);
1520 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1523 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1524 directory,lp_dontdescend(SNUM(conn))));
1525 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1526 check_descend = True;
1529 for (i=numentries;(i<maxentries) && !finished;i++) {
1530 finished = !get_dir_entry(ctx,
1541 char buf[DIR_STRUCT_SIZE];
1542 memcpy(buf,status,21);
1543 if (!make_dir_struct(ctx,
1549 convert_timespec_to_time_t(date),
1550 !allow_long_path_components)) {
1551 reply_nterror(req, NT_STATUS_NO_MEMORY);
1554 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1557 if (message_push_blob(&req->outbuf,
1558 data_blob_const(buf, sizeof(buf)))
1560 reply_nterror(req, NT_STATUS_NO_MEMORY);
1570 /* If we were called as SMBffirst with smb_search_id == NULL
1571 and no entries were found then return error and close dirptr
1574 if (numentries == 0) {
1575 dptr_close(sconn, &dptr_num);
1576 } else if(expect_close && status_len == 0) {
1577 /* Close the dptr - we know it's gone */
1578 dptr_close(sconn, &dptr_num);
1581 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1582 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1583 dptr_close(sconn, &dptr_num);
1586 if ((numentries == 0) && !mask_contains_wcard) {
1587 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1591 SSVAL(req->outbuf,smb_vwv0,numentries);
1592 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1593 SCVAL(smb_buf(req->outbuf),0,5);
1594 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1596 /* The replies here are never long name. */
1597 SSVAL(req->outbuf, smb_flg2,
1598 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1599 if (!allow_long_path_components) {
1600 SSVAL(req->outbuf, smb_flg2,
1601 SVAL(req->outbuf, smb_flg2)
1602 & (~FLAGS2_LONG_PATH_COMPONENTS));
1605 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1606 SSVAL(req->outbuf, smb_flg2,
1607 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1609 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1610 smb_fn_name(req->cmd),
1617 TALLOC_FREE(directory);
1618 TALLOC_FREE(smb_fname);
1619 END_PROFILE(SMBsearch);
1623 /****************************************************************************
1624 Reply to a fclose (stop directory search).
1625 ****************************************************************************/
1627 void reply_fclose(struct smb_request *req)
1635 bool path_contains_wcard = False;
1636 TALLOC_CTX *ctx = talloc_tos();
1637 struct smbd_server_connection *sconn = req->sconn;
1639 START_PROFILE(SMBfclose);
1641 if (lp_posix_pathnames()) {
1642 reply_unknown_new(req, req->cmd);
1643 END_PROFILE(SMBfclose);
1647 p = (const char *)req->buf + 1;
1648 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1649 &err, &path_contains_wcard);
1650 if (!NT_STATUS_IS_OK(err)) {
1651 reply_nterror(req, err);
1652 END_PROFILE(SMBfclose);
1656 status_len = SVAL(p,0);
1659 if (status_len == 0) {
1660 reply_force_doserror(req, ERRSRV, ERRsrverror);
1661 END_PROFILE(SMBfclose);
1665 memcpy(status,p,21);
1667 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1668 /* Close the dptr - we know it's gone */
1669 dptr_close(sconn, &dptr_num);
1672 reply_outbuf(req, 1, 0);
1673 SSVAL(req->outbuf,smb_vwv0,0);
1675 DEBUG(3,("search close\n"));
1677 END_PROFILE(SMBfclose);
1681 /****************************************************************************
1683 ****************************************************************************/
1685 void reply_open(struct smb_request *req)
1687 connection_struct *conn = req->conn;
1688 struct smb_filename *smb_fname = NULL;
1700 uint32 create_disposition;
1701 uint32 create_options = 0;
1702 uint32_t private_flags = 0;
1704 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1705 TALLOC_CTX *ctx = talloc_tos();
1707 START_PROFILE(SMBopen);
1710 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1714 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1715 deny_mode = SVAL(req->vwv+0, 0);
1716 dos_attr = SVAL(req->vwv+1, 0);
1718 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1719 STR_TERMINATE, &status);
1720 if (!NT_STATUS_IS_OK(status)) {
1721 reply_nterror(req, status);
1725 status = filename_convert(ctx,
1727 req->flags2 & FLAGS2_DFS_PATHNAMES,
1732 if (!NT_STATUS_IS_OK(status)) {
1733 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1734 reply_botherror(req,
1735 NT_STATUS_PATH_NOT_COVERED,
1736 ERRSRV, ERRbadpath);
1739 reply_nterror(req, status);
1743 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1744 OPENX_FILE_EXISTS_OPEN, &access_mask,
1745 &share_mode, &create_disposition,
1746 &create_options, &private_flags)) {
1747 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1751 status = SMB_VFS_CREATE_FILE(
1754 0, /* root_dir_fid */
1755 smb_fname, /* fname */
1756 access_mask, /* access_mask */
1757 share_mode, /* share_access */
1758 create_disposition, /* create_disposition*/
1759 create_options, /* create_options */
1760 dos_attr, /* file_attributes */
1761 oplock_request, /* oplock_request */
1762 0, /* allocation_size */
1769 if (!NT_STATUS_IS_OK(status)) {
1770 if (open_was_deferred(req->mid)) {
1771 /* We have re-scheduled this call. */
1774 reply_openerror(req, status);
1778 size = smb_fname->st.st_ex_size;
1779 fattr = dos_mode(conn, smb_fname);
1781 /* Deal with other possible opens having a modified
1783 if (ask_sharemode) {
1784 struct timespec write_time_ts;
1786 ZERO_STRUCT(write_time_ts);
1787 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1788 if (!null_timespec(write_time_ts)) {
1789 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1793 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1796 DEBUG(3,("attempt to open a directory %s\n",
1798 close_file(req, fsp, ERROR_CLOSE);
1799 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1800 ERRDOS, ERRnoaccess);
1804 reply_outbuf(req, 7, 0);
1805 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1806 SSVAL(req->outbuf,smb_vwv1,fattr);
1807 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1808 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1810 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1812 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1813 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1815 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1816 SCVAL(req->outbuf,smb_flg,
1817 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1820 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1821 SCVAL(req->outbuf,smb_flg,
1822 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1825 TALLOC_FREE(smb_fname);
1826 END_PROFILE(SMBopen);
1830 /****************************************************************************
1831 Reply to an open and X.
1832 ****************************************************************************/
1834 void reply_open_and_X(struct smb_request *req)
1836 connection_struct *conn = req->conn;
1837 struct smb_filename *smb_fname = NULL;
1842 /* Breakout the oplock request bits so we can set the
1843 reply bits separately. */
1844 int ex_oplock_request;
1845 int core_oplock_request;
1848 int smb_sattr = SVAL(req->vwv+4, 0);
1849 uint32 smb_time = make_unix_date3(req->vwv+6);
1857 uint64_t allocation_size;
1858 ssize_t retval = -1;
1861 uint32 create_disposition;
1862 uint32 create_options = 0;
1863 uint32_t private_flags = 0;
1864 TALLOC_CTX *ctx = talloc_tos();
1866 START_PROFILE(SMBopenX);
1868 if (req->wct < 15) {
1869 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1873 open_flags = SVAL(req->vwv+2, 0);
1874 deny_mode = SVAL(req->vwv+3, 0);
1875 smb_attr = SVAL(req->vwv+5, 0);
1876 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1877 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1878 oplock_request = ex_oplock_request | core_oplock_request;
1879 smb_ofun = SVAL(req->vwv+8, 0);
1880 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1882 /* If it's an IPC, pass off the pipe handler. */
1884 if (lp_nt_pipe_support()) {
1885 reply_open_pipe_and_X(conn, req);
1887 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1892 /* XXXX we need to handle passed times, sattr and flags */
1893 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1894 STR_TERMINATE, &status);
1895 if (!NT_STATUS_IS_OK(status)) {
1896 reply_nterror(req, status);
1900 status = filename_convert(ctx,
1902 req->flags2 & FLAGS2_DFS_PATHNAMES,
1907 if (!NT_STATUS_IS_OK(status)) {
1908 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1909 reply_botherror(req,
1910 NT_STATUS_PATH_NOT_COVERED,
1911 ERRSRV, ERRbadpath);
1914 reply_nterror(req, status);
1918 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1919 &access_mask, &share_mode,
1920 &create_disposition,
1923 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1927 status = SMB_VFS_CREATE_FILE(
1930 0, /* root_dir_fid */
1931 smb_fname, /* fname */
1932 access_mask, /* access_mask */
1933 share_mode, /* share_access */
1934 create_disposition, /* create_disposition*/
1935 create_options, /* create_options */
1936 smb_attr, /* file_attributes */
1937 oplock_request, /* oplock_request */
1938 0, /* allocation_size */
1943 &smb_action); /* pinfo */
1945 if (!NT_STATUS_IS_OK(status)) {
1946 if (open_was_deferred(req->mid)) {
1947 /* We have re-scheduled this call. */
1950 reply_openerror(req, status);
1954 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1955 if the file is truncated or created. */
1956 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1957 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1958 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1959 close_file(req, fsp, ERROR_CLOSE);
1960 reply_nterror(req, NT_STATUS_DISK_FULL);
1963 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1965 close_file(req, fsp, ERROR_CLOSE);
1966 reply_nterror(req, NT_STATUS_DISK_FULL);
1969 smb_fname->st.st_ex_size =
1970 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1973 fattr = dos_mode(conn, smb_fname);
1974 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1976 close_file(req, fsp, ERROR_CLOSE);
1977 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1981 /* If the caller set the extended oplock request bit
1982 and we granted one (by whatever means) - set the
1983 correct bit for extended oplock reply.
1986 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1987 smb_action |= EXTENDED_OPLOCK_GRANTED;
1990 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1991 smb_action |= EXTENDED_OPLOCK_GRANTED;
1994 /* If the caller set the core oplock request bit
1995 and we granted one (by whatever means) - set the
1996 correct bit for core oplock reply.
1999 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2000 reply_outbuf(req, 19, 0);
2002 reply_outbuf(req, 15, 0);
2005 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2006 SCVAL(req->outbuf, smb_flg,
2007 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2010 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2011 SCVAL(req->outbuf, smb_flg,
2012 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2015 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2016 SSVAL(req->outbuf,smb_vwv3,fattr);
2017 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2018 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2020 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2022 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2023 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2024 SSVAL(req->outbuf,smb_vwv11,smb_action);
2026 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2027 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2032 TALLOC_FREE(smb_fname);
2033 END_PROFILE(SMBopenX);
2037 /****************************************************************************
2038 Reply to a SMBulogoffX.
2039 ****************************************************************************/
2041 void reply_ulogoffX(struct smb_request *req)
2043 struct smbd_server_connection *sconn = req->sconn;
2046 START_PROFILE(SMBulogoffX);
2048 vuser = get_valid_user_struct(sconn, req->vuid);
2051 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2055 /* in user level security we are supposed to close any files
2056 open by this user */
2057 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2058 file_close_user(req->vuid);
2061 invalidate_vuid(sconn, req->vuid);
2063 reply_outbuf(req, 2, 0);
2065 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2067 END_PROFILE(SMBulogoffX);
2068 req->vuid = UID_FIELD_INVALID;
2072 /****************************************************************************
2073 Reply to a mknew or a create.
2074 ****************************************************************************/
2076 void reply_mknew(struct smb_request *req)
2078 connection_struct *conn = req->conn;
2079 struct smb_filename *smb_fname = NULL;
2082 struct smb_file_time ft;
2084 int oplock_request = 0;
2086 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2087 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2088 uint32 create_disposition;
2089 uint32 create_options = 0;
2090 TALLOC_CTX *ctx = talloc_tos();
2092 START_PROFILE(SMBcreate);
2096 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2100 fattr = SVAL(req->vwv+0, 0);
2101 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2104 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2106 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2107 STR_TERMINATE, &status);
2108 if (!NT_STATUS_IS_OK(status)) {
2109 reply_nterror(req, status);
2113 status = filename_convert(ctx,
2115 req->flags2 & FLAGS2_DFS_PATHNAMES,
2120 if (!NT_STATUS_IS_OK(status)) {
2121 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2122 reply_botherror(req,
2123 NT_STATUS_PATH_NOT_COVERED,
2124 ERRSRV, ERRbadpath);
2127 reply_nterror(req, status);
2131 if (fattr & aVOLID) {
2132 DEBUG(0,("Attempt to create file (%s) with volid set - "
2133 "please report this\n",
2134 smb_fname_str_dbg(smb_fname)));
2137 if(req->cmd == SMBmknew) {
2138 /* We should fail if file exists. */
2139 create_disposition = FILE_CREATE;
2141 /* Create if file doesn't exist, truncate if it does. */
2142 create_disposition = FILE_OVERWRITE_IF;
2145 status = SMB_VFS_CREATE_FILE(
2148 0, /* root_dir_fid */
2149 smb_fname, /* fname */
2150 access_mask, /* access_mask */
2151 share_mode, /* share_access */
2152 create_disposition, /* create_disposition*/
2153 create_options, /* create_options */
2154 fattr, /* file_attributes */
2155 oplock_request, /* oplock_request */
2156 0, /* allocation_size */
2157 0, /* private_flags */
2163 if (!NT_STATUS_IS_OK(status)) {
2164 if (open_was_deferred(req->mid)) {
2165 /* We have re-scheduled this call. */
2168 reply_openerror(req, status);
2172 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2173 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2174 if (!NT_STATUS_IS_OK(status)) {
2175 END_PROFILE(SMBcreate);
2179 reply_outbuf(req, 1, 0);
2180 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2182 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2183 SCVAL(req->outbuf,smb_flg,
2184 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2187 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2188 SCVAL(req->outbuf,smb_flg,
2189 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2192 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2193 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2194 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2195 (unsigned int)fattr));
2198 TALLOC_FREE(smb_fname);
2199 END_PROFILE(SMBcreate);
2203 /****************************************************************************
2204 Reply to a create temporary file.
2205 ****************************************************************************/
2207 void reply_ctemp(struct smb_request *req)
2209 connection_struct *conn = req->conn;
2210 struct smb_filename *smb_fname = NULL;
2218 TALLOC_CTX *ctx = talloc_tos();
2220 START_PROFILE(SMBctemp);
2223 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2227 fattr = SVAL(req->vwv+0, 0);
2228 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2230 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2231 STR_TERMINATE, &status);
2232 if (!NT_STATUS_IS_OK(status)) {
2233 reply_nterror(req, status);
2237 fname = talloc_asprintf(ctx,
2241 fname = talloc_strdup(ctx, "TMXXXXXX");
2245 reply_nterror(req, NT_STATUS_NO_MEMORY);
2249 status = filename_convert(ctx, conn,
2250 req->flags2 & FLAGS2_DFS_PATHNAMES,
2255 if (!NT_STATUS_IS_OK(status)) {
2256 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2257 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2258 ERRSRV, ERRbadpath);
2261 reply_nterror(req, status);
2265 tmpfd = mkstemp(smb_fname->base_name);
2267 reply_nterror(req, map_nt_error_from_unix(errno));
2271 SMB_VFS_STAT(conn, smb_fname);
2273 /* We should fail if file does not exist. */
2274 status = SMB_VFS_CREATE_FILE(
2277 0, /* root_dir_fid */
2278 smb_fname, /* fname */
2279 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2280 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2281 FILE_OPEN, /* create_disposition*/
2282 0, /* create_options */
2283 fattr, /* file_attributes */
2284 oplock_request, /* oplock_request */
2285 0, /* allocation_size */
2286 0, /* private_flags */
2292 /* close fd from mkstemp() */
2295 if (!NT_STATUS_IS_OK(status)) {
2296 if (open_was_deferred(req->mid)) {
2297 /* We have re-scheduled this call. */
2300 reply_openerror(req, status);
2304 reply_outbuf(req, 1, 0);
2305 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2307 /* the returned filename is relative to the directory */
2308 s = strrchr_m(fsp->fsp_name->base_name, '/');
2310 s = fsp->fsp_name->base_name;
2316 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2317 thing in the byte section. JRA */
2318 SSVALS(p, 0, -1); /* what is this? not in spec */
2320 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2322 reply_nterror(req, NT_STATUS_NO_MEMORY);
2326 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2327 SCVAL(req->outbuf, smb_flg,
2328 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2331 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2332 SCVAL(req->outbuf, smb_flg,
2333 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2336 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2337 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2338 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2340 TALLOC_FREE(smb_fname);
2341 END_PROFILE(SMBctemp);
2345 /*******************************************************************
2346 Check if a user is allowed to rename a file.
2347 ********************************************************************/
2349 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2354 if (!CAN_WRITE(conn)) {
2355 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2358 fmode = dos_mode(conn, fsp->fsp_name);
2359 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2360 return NT_STATUS_NO_SUCH_FILE;
2363 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2364 if (fsp->posix_open) {
2365 return NT_STATUS_OK;
2368 /* If no pathnames are open below this
2369 directory, allow the rename. */
2371 if (file_find_subpath(fsp)) {
2372 return NT_STATUS_ACCESS_DENIED;
2374 return NT_STATUS_OK;
2377 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2378 return NT_STATUS_OK;
2381 return NT_STATUS_ACCESS_DENIED;
2384 /*******************************************************************
2385 * unlink a file with all relevant access checks
2386 *******************************************************************/
2388 static NTSTATUS do_unlink(connection_struct *conn,
2389 struct smb_request *req,
2390 struct smb_filename *smb_fname,
2395 uint32 dirtype_orig = dirtype;
2398 bool posix_paths = lp_posix_pathnames();
2400 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2401 smb_fname_str_dbg(smb_fname),
2404 if (!CAN_WRITE(conn)) {
2405 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2409 ret = SMB_VFS_LSTAT(conn, smb_fname);
2411 ret = SMB_VFS_STAT(conn, smb_fname);
2414 return map_nt_error_from_unix(errno);
2417 fattr = dos_mode(conn, smb_fname);
2419 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2420 dirtype = aDIR|aARCH|aRONLY;
2423 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2425 return NT_STATUS_NO_SUCH_FILE;
2428 if (!dir_check_ftype(conn, fattr, dirtype)) {
2430 return NT_STATUS_FILE_IS_A_DIRECTORY;
2432 return NT_STATUS_NO_SUCH_FILE;
2435 if (dirtype_orig & 0x8000) {
2436 /* These will never be set for POSIX. */
2437 return NT_STATUS_NO_SUCH_FILE;
2441 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2442 return NT_STATUS_FILE_IS_A_DIRECTORY;
2445 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2446 return NT_STATUS_NO_SUCH_FILE;
2449 if (dirtype & 0xFF00) {
2450 /* These will never be set for POSIX. */
2451 return NT_STATUS_NO_SUCH_FILE;
2456 return NT_STATUS_NO_SUCH_FILE;
2459 /* Can't delete a directory. */
2461 return NT_STATUS_FILE_IS_A_DIRECTORY;
2466 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2467 return NT_STATUS_OBJECT_NAME_INVALID;
2468 #endif /* JRATEST */
2470 /* On open checks the open itself will check the share mode, so
2471 don't do it here as we'll get it wrong. */
2473 status = SMB_VFS_CREATE_FILE
2476 0, /* root_dir_fid */
2477 smb_fname, /* fname */
2478 DELETE_ACCESS, /* access_mask */
2479 FILE_SHARE_NONE, /* share_access */
2480 FILE_OPEN, /* create_disposition*/
2481 FILE_NON_DIRECTORY_FILE, /* create_options */
2482 /* file_attributes */
2483 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2484 FILE_ATTRIBUTE_NORMAL,
2485 0, /* oplock_request */
2486 0, /* allocation_size */
2487 0, /* private_flags */
2493 if (!NT_STATUS_IS_OK(status)) {
2494 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2495 nt_errstr(status)));
2499 status = can_set_delete_on_close(fsp, fattr);
2500 if (!NT_STATUS_IS_OK(status)) {
2501 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2503 smb_fname_str_dbg(smb_fname),
2504 nt_errstr(status)));
2505 close_file(req, fsp, NORMAL_CLOSE);
2509 /* The set is across all open files on this dev/inode pair. */
2510 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2511 close_file(req, fsp, NORMAL_CLOSE);
2512 return NT_STATUS_ACCESS_DENIED;
2515 return close_file(req, fsp, NORMAL_CLOSE);
2518 /****************************************************************************
2519 The guts of the unlink command, split out so it may be called by the NT SMB
2521 ****************************************************************************/
2523 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2524 uint32 dirtype, struct smb_filename *smb_fname,
2527 char *fname_dir = NULL;
2528 char *fname_mask = NULL;
2530 NTSTATUS status = NT_STATUS_OK;
2531 TALLOC_CTX *ctx = talloc_tos();
2533 /* Split up the directory from the filename/mask. */
2534 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2535 &fname_dir, &fname_mask);
2536 if (!NT_STATUS_IS_OK(status)) {
2541 * We should only check the mangled cache
2542 * here if unix_convert failed. This means
2543 * that the path in 'mask' doesn't exist
2544 * on the file system and so we need to look
2545 * for a possible mangle. This patch from
2546 * Tine Smukavec <valentin.smukavec@hermes.si>.
2549 if (!VALID_STAT(smb_fname->st) &&
2550 mangle_is_mangled(fname_mask, conn->params)) {
2551 char *new_mask = NULL;
2552 mangle_lookup_name_from_8_3(ctx, fname_mask,
2553 &new_mask, conn->params);
2555 TALLOC_FREE(fname_mask);
2556 fname_mask = new_mask;
2563 * Only one file needs to be unlinked. Append the mask back
2564 * onto the directory.
2566 TALLOC_FREE(smb_fname->base_name);
2567 smb_fname->base_name = talloc_asprintf(smb_fname,
2571 if (!smb_fname->base_name) {
2572 status = NT_STATUS_NO_MEMORY;
2576 dirtype = FILE_ATTRIBUTE_NORMAL;
2579 status = check_name(conn, smb_fname->base_name);
2580 if (!NT_STATUS_IS_OK(status)) {
2584 status = do_unlink(conn, req, smb_fname, dirtype);
2585 if (!NT_STATUS_IS_OK(status)) {
2591 struct smb_Dir *dir_hnd = NULL;
2593 const char *dname = NULL;
2594 char *talloced = NULL;
2596 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2597 status = NT_STATUS_OBJECT_NAME_INVALID;
2601 if (strequal(fname_mask,"????????.???")) {
2602 TALLOC_FREE(fname_mask);
2603 fname_mask = talloc_strdup(ctx, "*");
2605 status = NT_STATUS_NO_MEMORY;
2610 status = check_name(conn, fname_dir);
2611 if (!NT_STATUS_IS_OK(status)) {
2615 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2617 if (dir_hnd == NULL) {
2618 status = map_nt_error_from_unix(errno);
2622 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2623 the pattern matches against the long name, otherwise the short name
2624 We don't implement this yet XXXX
2627 status = NT_STATUS_NO_SUCH_FILE;
2629 while ((dname = ReadDirName(dir_hnd, &offset,
2630 &smb_fname->st, &talloced))) {
2631 TALLOC_CTX *frame = talloc_stackframe();
2633 if (!is_visible_file(conn, fname_dir, dname,
2634 &smb_fname->st, true)) {
2636 TALLOC_FREE(talloced);
2640 /* Quick check for "." and ".." */
2641 if (ISDOT(dname) || ISDOTDOT(dname)) {
2643 TALLOC_FREE(talloced);
2647 if(!mask_match(dname, fname_mask,
2648 conn->case_sensitive)) {
2650 TALLOC_FREE(talloced);
2654 TALLOC_FREE(smb_fname->base_name);
2655 smb_fname->base_name =
2656 talloc_asprintf(smb_fname, "%s/%s",
2659 if (!smb_fname->base_name) {
2660 TALLOC_FREE(dir_hnd);
2661 status = NT_STATUS_NO_MEMORY;
2663 TALLOC_FREE(talloced);
2667 status = check_name(conn, smb_fname->base_name);
2668 if (!NT_STATUS_IS_OK(status)) {
2669 TALLOC_FREE(dir_hnd);
2671 TALLOC_FREE(talloced);
2675 status = do_unlink(conn, req, smb_fname, dirtype);
2676 if (!NT_STATUS_IS_OK(status)) {
2678 TALLOC_FREE(talloced);
2683 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2684 smb_fname->base_name));
2687 TALLOC_FREE(talloced);
2689 TALLOC_FREE(dir_hnd);
2692 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2693 status = map_nt_error_from_unix(errno);
2697 TALLOC_FREE(fname_dir);
2698 TALLOC_FREE(fname_mask);
2702 /****************************************************************************
2704 ****************************************************************************/
2706 void reply_unlink(struct smb_request *req)
2708 connection_struct *conn = req->conn;
2710 struct smb_filename *smb_fname = NULL;
2713 bool path_contains_wcard = False;
2714 TALLOC_CTX *ctx = talloc_tos();
2716 START_PROFILE(SMBunlink);
2719 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2723 dirtype = SVAL(req->vwv+0, 0);
2725 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2726 STR_TERMINATE, &status,
2727 &path_contains_wcard);
2728 if (!NT_STATUS_IS_OK(status)) {
2729 reply_nterror(req, status);
2733 status = filename_convert(ctx, conn,
2734 req->flags2 & FLAGS2_DFS_PATHNAMES,
2736 UCF_COND_ALLOW_WCARD_LCOMP,
2737 &path_contains_wcard,
2739 if (!NT_STATUS_IS_OK(status)) {
2740 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2741 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2742 ERRSRV, ERRbadpath);
2745 reply_nterror(req, status);
2749 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2751 status = unlink_internals(conn, req, dirtype, smb_fname,
2752 path_contains_wcard);
2753 if (!NT_STATUS_IS_OK(status)) {
2754 if (open_was_deferred(req->mid)) {
2755 /* We have re-scheduled this call. */
2758 reply_nterror(req, status);
2762 reply_outbuf(req, 0, 0);
2764 TALLOC_FREE(smb_fname);
2765 END_PROFILE(SMBunlink);
2769 /****************************************************************************
2771 ****************************************************************************/
2773 static void fail_readraw(void)
2775 const char *errstr = talloc_asprintf(talloc_tos(),
2776 "FAIL ! reply_readbraw: socket write fail (%s)",
2781 exit_server_cleanly(errstr);
2784 /****************************************************************************
2785 Fake (read/write) sendfile. Returns -1 on read or write fail.
2786 ****************************************************************************/
2788 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2792 size_t tosend = nread;
2799 bufsize = MIN(nread, 65536);
2801 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2805 while (tosend > 0) {
2809 if (tosend > bufsize) {
2814 ret = read_file(fsp,buf,startpos,cur_read);
2820 /* If we had a short read, fill with zeros. */
2821 if (ret < cur_read) {
2822 memset(buf + ret, '\0', cur_read - ret);
2825 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2830 startpos += cur_read;
2834 return (ssize_t)nread;
2837 #if defined(WITH_SENDFILE)
2838 /****************************************************************************
2839 Deal with the case of sendfile reading less bytes from the file than
2840 requested. Fill with zeros (all we can do).
2841 ****************************************************************************/
2843 static void sendfile_short_send(files_struct *fsp,
2848 #define SHORT_SEND_BUFSIZE 1024
2849 if (nread < headersize) {
2850 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2851 "header for file %s (%s). Terminating\n",
2852 fsp_str_dbg(fsp), strerror(errno)));
2853 exit_server_cleanly("sendfile_short_send failed");
2856 nread -= headersize;
2858 if (nread < smb_maxcnt) {
2859 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2861 exit_server_cleanly("sendfile_short_send: "
2865 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2866 "with zeros !\n", fsp_str_dbg(fsp)));
2868 while (nread < smb_maxcnt) {
2870 * We asked for the real file size and told sendfile
2871 * to not go beyond the end of the file. But it can
2872 * happen that in between our fstat call and the
2873 * sendfile call the file was truncated. This is very
2874 * bad because we have already announced the larger
2875 * number of bytes to the client.
2877 * The best we can do now is to send 0-bytes, just as
2878 * a read from a hole in a sparse file would do.
2880 * This should happen rarely enough that I don't care
2881 * about efficiency here :-)
2885 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2886 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2887 exit_server_cleanly("sendfile_short_send: "
2888 "write_data failed");
2895 #endif /* defined WITH_SENDFILE */
2897 /****************************************************************************
2898 Return a readbraw error (4 bytes of zero).
2899 ****************************************************************************/
2901 static void reply_readbraw_error(void)
2907 smbd_lock_socket(smbd_server_conn);
2908 if (write_data(smbd_server_fd(),header,4) != 4) {
2911 smbd_unlock_socket(smbd_server_conn);
2914 /****************************************************************************
2915 Use sendfile in readbraw.
2916 ****************************************************************************/
2918 static void send_file_readbraw(connection_struct *conn,
2919 struct smb_request *req,
2925 char *outbuf = NULL;
2928 #if defined(WITH_SENDFILE)
2930 * We can only use sendfile on a non-chained packet
2931 * but we can use on a non-oplocked file. tridge proved this
2932 * on a train in Germany :-). JRA.
2933 * reply_readbraw has already checked the length.
2936 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2937 (fsp->wcp == NULL) &&
2938 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
2939 ssize_t sendfile_read = -1;
2941 DATA_BLOB header_blob;
2943 _smb_setlen(header,nread);
2944 header_blob = data_blob_const(header, 4);
2946 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2947 &header_blob, startpos, nread)) == -1) {
2948 /* Returning ENOSYS means no data at all was sent.
2949 * Do this as a normal read. */
2950 if (errno == ENOSYS) {
2951 goto normal_readbraw;
2955 * Special hack for broken Linux with no working sendfile. If we
2956 * return EINTR we sent the header but not the rest of the data.
2957 * Fake this up by doing read/write calls.
2959 if (errno == EINTR) {
2960 /* Ensure we don't do this again. */
2961 set_use_sendfile(SNUM(conn), False);
2962 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2964 if (fake_sendfile(fsp, startpos, nread) == -1) {
2965 DEBUG(0,("send_file_readbraw: "
2966 "fake_sendfile failed for "
2970 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2975 DEBUG(0,("send_file_readbraw: sendfile failed for "
2976 "file %s (%s). Terminating\n",
2977 fsp_str_dbg(fsp), strerror(errno)));
2978 exit_server_cleanly("send_file_readbraw sendfile failed");
2979 } else if (sendfile_read == 0) {
2981 * Some sendfile implementations return 0 to indicate
2982 * that there was a short read, but nothing was
2983 * actually written to the socket. In this case,
2984 * fallback to the normal read path so the header gets
2985 * the correct byte count.
2987 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2988 "bytes falling back to the normal read: "
2989 "%s\n", fsp_str_dbg(fsp)));
2990 goto normal_readbraw;
2993 /* Deal with possible short send. */
2994 if (sendfile_read != 4+nread) {
2995 sendfile_short_send(fsp, sendfile_read, 4, nread);
3003 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3005 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3006 (unsigned)(nread+4)));
3007 reply_readbraw_error();
3012 ret = read_file(fsp,outbuf+4,startpos,nread);
3013 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3022 _smb_setlen(outbuf,ret);
3023 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3026 TALLOC_FREE(outbuf);
3029 /****************************************************************************
3030 Reply to a readbraw (core+ protocol).
3031 ****************************************************************************/
3033 void reply_readbraw(struct smb_request *req)
3035 connection_struct *conn = req->conn;
3036 struct smbd_server_connection *sconn = req->sconn;
3037 ssize_t maxcount,mincount;
3041 struct lock_struct lock;
3044 START_PROFILE(SMBreadbraw);
3046 if (srv_is_signing_active(sconn) ||
3047 is_encrypted_packet(req->inbuf)) {
3048 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3049 "raw reads/writes are disallowed.");
3053 reply_readbraw_error();
3054 END_PROFILE(SMBreadbraw);
3058 if (sconn->smb1.echo_handler.trusted_fde) {
3059 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3060 "'async smb echo handler = yes'\n"));
3061 reply_readbraw_error();
3062 END_PROFILE(SMBreadbraw);
3067 * Special check if an oplock break has been issued
3068 * and the readraw request croses on the wire, we must
3069 * return a zero length response here.
3072 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3075 * We have to do a check_fsp by hand here, as
3076 * we must always return 4 zero bytes on error,
3080 if (!fsp || !conn || conn != fsp->conn ||
3081 req->vuid != fsp->vuid ||
3082 fsp->is_directory || fsp->fh->fd == -1) {
3084 * fsp could be NULL here so use the value from the packet. JRA.
3086 DEBUG(3,("reply_readbraw: fnum %d not valid "
3088 (int)SVAL(req->vwv+0, 0)));
3089 reply_readbraw_error();
3090 END_PROFILE(SMBreadbraw);
3094 /* Do a "by hand" version of CHECK_READ. */
3095 if (!(fsp->can_read ||
3096 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3097 (fsp->access_mask & FILE_EXECUTE)))) {
3098 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3099 (int)SVAL(req->vwv+0, 0)));
3100 reply_readbraw_error();
3101 END_PROFILE(SMBreadbraw);
3105 flush_write_cache(fsp, READRAW_FLUSH);
3107 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3108 if(req->wct == 10) {
3110 * This is a large offset (64 bit) read.
3112 #ifdef LARGE_SMB_OFF_T
3114 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3116 #else /* !LARGE_SMB_OFF_T */
3119 * Ensure we haven't been sent a >32 bit offset.
3122 if(IVAL(req->vwv+8, 0) != 0) {
3123 DEBUG(0,("reply_readbraw: large offset "
3124 "(%x << 32) used and we don't support "
3125 "64 bit offsets.\n",
3126 (unsigned int)IVAL(req->vwv+8, 0) ));
3127 reply_readbraw_error();
3128 END_PROFILE(SMBreadbraw);
3132 #endif /* LARGE_SMB_OFF_T */
3135 DEBUG(0,("reply_readbraw: negative 64 bit "
3136 "readraw offset (%.0f) !\n",
3137 (double)startpos ));
3138 reply_readbraw_error();
3139 END_PROFILE(SMBreadbraw);
3144 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3145 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3147 /* ensure we don't overrun the packet size */
3148 maxcount = MIN(65535,maxcount);
3150 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3151 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3154 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3155 reply_readbraw_error();
3156 END_PROFILE(SMBreadbraw);
3160 if (fsp_stat(fsp) == 0) {
3161 size = fsp->fsp_name->st.st_ex_size;
3164 if (startpos >= size) {
3167 nread = MIN(maxcount,(size - startpos));
3170 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3171 if (nread < mincount)
3175 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3176 "min=%lu nread=%lu\n",
3177 fsp->fnum, (double)startpos,
3178 (unsigned long)maxcount,
3179 (unsigned long)mincount,
3180 (unsigned long)nread ) );
3182 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3184 DEBUG(5,("reply_readbraw finished\n"));
3186 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3188 END_PROFILE(SMBreadbraw);
3193 #define DBGC_CLASS DBGC_LOCKING
3195 /****************************************************************************
3196 Reply to a lockread (core+ protocol).
3197 ****************************************************************************/
3199 void reply_lockread(struct smb_request *req)
3201 connection_struct *conn = req->conn;
3208 struct byte_range_lock *br_lck = NULL;
3210 struct smbd_server_connection *sconn = smbd_server_conn;
3212 START_PROFILE(SMBlockread);
3215 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3216 END_PROFILE(SMBlockread);
3220 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3222 if (!check_fsp(conn, req, fsp)) {
3223 END_PROFILE(SMBlockread);
3227 if (!CHECK_READ(fsp,req)) {
3228 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3229 END_PROFILE(SMBlockread);
3233 numtoread = SVAL(req->vwv+1, 0);
3234 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3236 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3238 reply_outbuf(req, 5, numtoread + 3);
3240 data = smb_buf(req->outbuf) + 3;
3243 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3244 * protocol request that predates the read/write lock concept.
3245 * Thus instead of asking for a read lock here we need to ask
3246 * for a write lock. JRA.
3247 * Note that the requested lock size is unaffected by max_recv.
3250 br_lck = do_lock(smbd_messaging_context(),
3252 (uint64_t)req->smbpid,
3253 (uint64_t)numtoread,
3257 False, /* Non-blocking lock. */
3261 TALLOC_FREE(br_lck);
3263 if (NT_STATUS_V(status)) {
3264 reply_nterror(req, status);
3265 END_PROFILE(SMBlockread);
3270 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3273 if (numtoread > sconn->smb1.negprot.max_recv) {
3274 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3275 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3276 (unsigned int)numtoread,
3277 (unsigned int)sconn->smb1.negprot.max_recv));
3278 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3280 nread = read_file(fsp,data,startpos,numtoread);
3283 reply_nterror(req, map_nt_error_from_unix(errno));
3284 END_PROFILE(SMBlockread);
3288 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3290 SSVAL(req->outbuf,smb_vwv0,nread);
3291 SSVAL(req->outbuf,smb_vwv5,nread+3);
3292 p = smb_buf(req->outbuf);
3293 SCVAL(p,0,0); /* pad byte. */
3296 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3297 fsp->fnum, (int)numtoread, (int)nread));
3299 END_PROFILE(SMBlockread);
3304 #define DBGC_CLASS DBGC_ALL
3306 /****************************************************************************
3308 ****************************************************************************/
3310 void reply_read(struct smb_request *req)
3312 connection_struct *conn = req->conn;
3319 struct lock_struct lock;
3320 struct smbd_server_connection *sconn = smbd_server_conn;
3322 START_PROFILE(SMBread);
3325 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3326 END_PROFILE(SMBread);
3330 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3332 if (!check_fsp(conn, req, fsp)) {
3333 END_PROFILE(SMBread);
3337 if (!CHECK_READ(fsp,req)) {
3338 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3339 END_PROFILE(SMBread);
3343 numtoread = SVAL(req->vwv+1, 0);
3344 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3346 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3349 * The requested read size cannot be greater than max_recv. JRA.
3351 if (numtoread > sconn->smb1.negprot.max_recv) {
3352 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3353 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3354 (unsigned int)numtoread,
3355 (unsigned int)sconn->smb1.negprot.max_recv));
3356 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3359 reply_outbuf(req, 5, numtoread+3);
3361 data = smb_buf(req->outbuf) + 3;
3363 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3364 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3367 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3368 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3369 END_PROFILE(SMBread);
3374 nread = read_file(fsp,data,startpos,numtoread);
3377 reply_nterror(req, map_nt_error_from_unix(errno));
3381 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3383 SSVAL(req->outbuf,smb_vwv0,nread);
3384 SSVAL(req->outbuf,smb_vwv5,nread+3);
3385 SCVAL(smb_buf(req->outbuf),0,1);
3386 SSVAL(smb_buf(req->outbuf),1,nread);
3388 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3389 fsp->fnum, (int)numtoread, (int)nread ) );
3392 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3394 END_PROFILE(SMBread);
3398 /****************************************************************************
3400 ****************************************************************************/
3402 static int setup_readX_header(struct smb_request *req, char *outbuf,
3408 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3409 data = smb_buf(outbuf);
3411 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3413 SCVAL(outbuf,smb_vwv0,0xFF);
3414 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3415 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3416 SSVAL(outbuf,smb_vwv6,
3418 + 1 /* the wct field */
3419 + 12 * sizeof(uint16_t) /* vwv */
3420 + 2); /* the buflen field */
3421 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3422 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3423 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3424 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3428 /****************************************************************************
3429 Reply to a read and X - possibly using sendfile.
3430 ****************************************************************************/
3432 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3433 files_struct *fsp, SMB_OFF_T startpos,
3437 struct lock_struct lock;
3438 int saved_errno = 0;
3440 if(fsp_stat(fsp) == -1) {
3441 reply_nterror(req, map_nt_error_from_unix(errno));
3445 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3446 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3449 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3450 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3454 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3455 (startpos > fsp->fsp_name->st.st_ex_size)
3456 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3458 * We already know that we would do a short read, so don't
3459 * try the sendfile() path.
3461 goto nosendfile_read;
3464 #if defined(WITH_SENDFILE)
3466 * We can only use sendfile on a non-chained packet
3467 * but we can use on a non-oplocked file. tridge proved this
3468 * on a train in Germany :-). JRA.
3471 if (!req_is_in_chain(req) &&
3472 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3473 (fsp->wcp == NULL) &&
3474 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3475 uint8 headerbuf[smb_size + 12 * 2];
3479 * Set up the packet header before send. We
3480 * assume here the sendfile will work (get the
3481 * correct amount of data).
3484 header = data_blob_const(headerbuf, sizeof(headerbuf));
3486 construct_reply_common_req(req, (char *)headerbuf);
3487 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3489 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3490 /* Returning ENOSYS means no data at all was sent.
3491 Do this as a normal read. */
3492 if (errno == ENOSYS) {
3497 * Special hack for broken Linux with no working sendfile. If we
3498 * return EINTR we sent the header but not the rest of the data.
3499 * Fake this up by doing read/write calls.
3502 if (errno == EINTR) {
3503 /* Ensure we don't do this again. */
3504 set_use_sendfile(SNUM(conn), False);
3505 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3506 nread = fake_sendfile(fsp, startpos,
3509 DEBUG(0,("send_file_readX: "
3510 "fake_sendfile failed for "
3514 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3516 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3517 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3518 /* No outbuf here means successful sendfile. */
3522 DEBUG(0,("send_file_readX: sendfile failed for file "
3523 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3525 exit_server_cleanly("send_file_readX sendfile failed");
3526 } else if (nread == 0) {
3528 * Some sendfile implementations return 0 to indicate
3529 * that there was a short read, but nothing was
3530 * actually written to the socket. In this case,
3531 * fallback to the normal read path so the header gets
3532 * the correct byte count.
3534 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3535 "falling back to the normal read: %s\n",
3540 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3541 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3543 /* Deal with possible short send. */
3544 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3545 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3547 /* No outbuf here means successful sendfile. */
3548 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3549 SMB_PERFCOUNT_END(&req->pcd);
3557 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3558 uint8 headerbuf[smb_size + 2*12];
3560 construct_reply_common_req(req, (char *)headerbuf);
3561 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3563 /* Send out the header. */
3564 if (write_data(smbd_server_fd(), (char *)headerbuf,
3565 sizeof(headerbuf)) != sizeof(headerbuf)) {
3566 DEBUG(0,("send_file_readX: write_data failed for file "
3567 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3569 exit_server_cleanly("send_file_readX sendfile failed");
3571 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3573 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3574 "file %s (%s).\n", fsp_str_dbg(fsp),
3576 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3583 reply_outbuf(req, 12, smb_maxcnt);
3585 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3586 saved_errno = errno;
3588 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3591 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3595 setup_readX_header(req, (char *)req->outbuf, nread);
3597 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3598 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3604 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3605 TALLOC_FREE(req->outbuf);
3609 /****************************************************************************
3610 Reply to a read and X.
3611 ****************************************************************************/
3613 void reply_read_and_X(struct smb_request *req)
3615 connection_struct *conn = req->conn;
3619 bool big_readX = False;
3621 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3624 START_PROFILE(SMBreadX);
3626 if ((req->wct != 10) && (req->wct != 12)) {
3627 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3631 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3632 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3633 smb_maxcnt = SVAL(req->vwv+5, 0);
3635 /* If it's an IPC, pass off the pipe handler. */
3637 reply_pipe_read_and_X(req);
3638 END_PROFILE(SMBreadX);
3642 if (!check_fsp(conn, req, fsp)) {
3643 END_PROFILE(SMBreadX);
3647 if (!CHECK_READ(fsp,req)) {
3648 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3649 END_PROFILE(SMBreadX);
3653 if (global_client_caps & CAP_LARGE_READX) {
3654 size_t upper_size = SVAL(req->vwv+7, 0);
3655 smb_maxcnt |= (upper_size<<16);
3656 if (upper_size > 1) {
3657 /* Can't do this on a chained packet. */
3658 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3659 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3660 END_PROFILE(SMBreadX);
3663 /* We currently don't do this on signed or sealed data. */
3664 if (srv_is_signing_active(smbd_server_conn) ||
3665 is_encrypted_packet(req->inbuf)) {
3666 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3667 END_PROFILE(SMBreadX);
3670 /* Is there room in the reply for this data ? */
3671 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3673 NT_STATUS_INVALID_PARAMETER);
3674 END_PROFILE(SMBreadX);
3681 if (req->wct == 12) {
3682 #ifdef LARGE_SMB_OFF_T
3684 * This is a large offset (64 bit) read.
3686 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3688 #else /* !LARGE_SMB_OFF_T */
3691 * Ensure we haven't been sent a >32 bit offset.
3694 if(IVAL(req->vwv+10, 0) != 0) {
3695 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3696 "used and we don't support 64 bit offsets.\n",
3697 (unsigned int)IVAL(req->vwv+10, 0) ));
3698 END_PROFILE(SMBreadX);
3699 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3703 #endif /* LARGE_SMB_OFF_T */
3708 NTSTATUS status = schedule_aio_read_and_X(conn,
3713 if (NT_STATUS_IS_OK(status)) {
3714 /* Read scheduled - we're done. */
3717 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3718 /* Real error - report to client. */
3719 END_PROFILE(SMBreadX);
3720 reply_nterror(req, status);
3723 /* NT_STATUS_RETRY - fall back to sync read. */
3726 smbd_lock_socket(smbd_server_conn);
3727 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3728 smbd_unlock_socket(smbd_server_conn);
3731 END_PROFILE(SMBreadX);
3735 /****************************************************************************
3736 Error replies to writebraw must have smb_wct == 1. Fix this up.
3737 ****************************************************************************/
3739 void error_to_writebrawerr(struct smb_request *req)
3741 uint8 *old_outbuf = req->outbuf;
3743 reply_outbuf(req, 1, 0);
3745 memcpy(req->outbuf, old_outbuf, smb_size);
3746 TALLOC_FREE(old_outbuf);
3749 /****************************************************************************
3750 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3751 ****************************************************************************/
3753 void reply_writebraw(struct smb_request *req)
3755 connection_struct *conn = req->conn;
3758 ssize_t total_written=0;
3759 size_t numtowrite=0;
3765 struct lock_struct lock;
3768 START_PROFILE(SMBwritebraw);
3771 * If we ever reply with an error, it must have the SMB command
3772 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3775 SCVAL(req->inbuf,smb_com,SMBwritec);
3777 if (srv_is_signing_active(smbd_server_conn)) {
3778 END_PROFILE(SMBwritebraw);
3779 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3780 "raw reads/writes are disallowed.");
3783 if (req->wct < 12) {
3784 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3785 error_to_writebrawerr(req);
3786 END_PROFILE(SMBwritebraw);
3790 if (smbd_server_conn->smb1.echo_handler.trusted_fde) {
3791 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3792 "'async smb echo handler = yes'\n"));
3793 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3794 error_to_writebrawerr(req);
3795 END_PROFILE(SMBwritebraw);
3799 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3800 if (!check_fsp(conn, req, fsp)) {
3801 error_to_writebrawerr(req);
3802 END_PROFILE(SMBwritebraw);
3806 if (!CHECK_WRITE(fsp)) {
3807 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3808 error_to_writebrawerr(req);
3809 END_PROFILE(SMBwritebraw);
3813 tcount = IVAL(req->vwv+1, 0);
3814 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3815 write_through = BITSETW(req->vwv+7,0);
3817 /* We have to deal with slightly different formats depending
3818 on whether we are using the core+ or lanman1.0 protocol */
3820 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3821 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3822 data = smb_buf(req->inbuf);
3824 numtowrite = SVAL(req->vwv+10, 0);
3825 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3828 /* Ensure we don't write bytes past the end of this packet. */
3829 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3831 error_to_writebrawerr(req);
3832 END_PROFILE(SMBwritebraw);
3836 if (!fsp->print_file) {
3837 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3838 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3841 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3842 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3843 error_to_writebrawerr(req);
3844 END_PROFILE(SMBwritebraw);
3850 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3853 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3854 "wrote=%d sync=%d\n",
3855 fsp->fnum, (double)startpos, (int)numtowrite,
3856 (int)nwritten, (int)write_through));
3858 if (nwritten < (ssize_t)numtowrite) {
3859 reply_nterror(req, NT_STATUS_DISK_FULL);
3860 error_to_writebrawerr(req);
3864 total_written = nwritten;
3866 /* Allocate a buffer of 64k + length. */
3867 buf = TALLOC_ARRAY(NULL, char, 65540);
3869 reply_nterror(req, NT_STATUS_NO_MEMORY);
3870 error_to_writebrawerr(req);
3874 /* Return a SMBwritebraw message to the redirector to tell
3875 * it to send more bytes */
3877 memcpy(buf, req->inbuf, smb_size);
3878 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3879 SCVAL(buf,smb_com,SMBwritebraw);
3880 SSVALS(buf,smb_vwv0,0xFFFF);
3882 if (!srv_send_smb(smbd_server_fd(),
3884 false, 0, /* no signing */
3885 IS_CONN_ENCRYPTED(conn),
3887 exit_server_cleanly("reply_writebraw: srv_send_smb "
3891 /* Now read the raw data into the buffer and write it */
3892 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3894 if (!NT_STATUS_IS_OK(status)) {
3895 exit_server_cleanly("secondary writebraw failed");
3898 /* Set up outbuf to return the correct size */
3899 reply_outbuf(req, 1, 0);
3901 if (numtowrite != 0) {
3903 if (numtowrite > 0xFFFF) {
3904 DEBUG(0,("reply_writebraw: Oversize secondary write "
3905 "raw requested (%u). Terminating\n",
3906 (unsigned int)numtowrite ));
3907 exit_server_cleanly("secondary writebraw failed");
3910 if (tcount > nwritten+numtowrite) {
3911 DEBUG(3,("reply_writebraw: Client overestimated the "
3913 (int)tcount,(int)nwritten,(int)numtowrite));
3916 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3918 if (!NT_STATUS_IS_OK(status)) {
3919 DEBUG(0,("reply_writebraw: Oversize secondary write "
3920 "raw read failed (%s). Terminating\n",
3921 nt_errstr(status)));
3922 exit_server_cleanly("secondary writebraw failed");
3925 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3926 if (nwritten == -1) {
3928 reply_nterror(req, map_nt_error_from_unix(errno));
3929 error_to_writebrawerr(req);
3933 if (nwritten < (ssize_t)numtowrite) {
3934 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3935 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3939 total_written += nwritten;
3944 SSVAL(req->outbuf,smb_vwv0,total_written);
3946 status = sync_file(conn, fsp, write_through);
3947 if (!NT_STATUS_IS_OK(status)) {
3948 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3949 fsp_str_dbg(fsp), nt_errstr(status)));
3950 reply_nterror(req, status);
3951 error_to_writebrawerr(req);
3955 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3957 fsp->fnum, (double)startpos, (int)numtowrite,
3958 (int)total_written));
3960 if (!fsp->print_file) {
3961 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3964 /* We won't return a status if write through is not selected - this
3965 * follows what WfWg does */
3966 END_PROFILE(SMBwritebraw);
3968 if (!write_through && total_written==tcount) {
3970 #if RABBIT_PELLET_FIX
3972 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3973 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3976 if (!send_keepalive(smbd_server_fd())) {
3977 exit_server_cleanly("reply_writebraw: send of "
3978 "keepalive failed");
3981 TALLOC_FREE(req->outbuf);
3986 if (!fsp->print_file) {
3987 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3990 END_PROFILE(SMBwritebraw);
3995 #define DBGC_CLASS DBGC_LOCKING
3997 /****************************************************************************
3998 Reply to a writeunlock (core+).
3999 ****************************************************************************/
4001 void reply_writeunlock(struct smb_request *req)
4003 connection_struct *conn = req->conn;
4004 ssize_t nwritten = -1;
4008 NTSTATUS status = NT_STATUS_OK;
4010 struct lock_struct lock;
4011 int saved_errno = 0;
4013 START_PROFILE(SMBwriteunlock);
4016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4017 END_PROFILE(SMBwriteunlock);
4021 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4023 if (!check_fsp(conn, req, fsp)) {
4024 END_PROFILE(SMBwriteunlock);
4028 if (!CHECK_WRITE(fsp)) {
4029 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4030 END_PROFILE(SMBwriteunlock);
4034 numtowrite = SVAL(req->vwv+1, 0);
4035 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4036 data = (const char *)req->buf + 3;
4038 if (!fsp->print_file && numtowrite > 0) {
4039 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4040 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4043 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4044 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4045 END_PROFILE(SMBwriteunlock);
4050 /* The special X/Open SMB protocol handling of
4051 zero length writes is *NOT* done for
4053 if(numtowrite == 0) {
4056 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4057 saved_errno = errno;
4060 status = sync_file(conn, fsp, False /* write through */);
4061 if (!NT_STATUS_IS_OK(status)) {
4062 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4063 fsp_str_dbg(fsp), nt_errstr(status)));
4064 reply_nterror(req, status);
4069 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4073 if((nwritten < numtowrite) && (numtowrite != 0)) {
4074 reply_nterror(req, NT_STATUS_DISK_FULL);
4078 if (numtowrite && !fsp->print_file) {
4079 status = do_unlock(smbd_messaging_context(),
4081 (uint64_t)req->smbpid,
4082 (uint64_t)numtowrite,
4086 if (NT_STATUS_V(status)) {
4087 reply_nterror(req, status);
4092 reply_outbuf(req, 1, 0);
4094 SSVAL(req->outbuf,smb_vwv0,nwritten);
4096 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4097 fsp->fnum, (int)numtowrite, (int)nwritten));
4100 if (numtowrite && !fsp->print_file) {
4101 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4104 END_PROFILE(SMBwriteunlock);
4109 #define DBGC_CLASS DBGC_ALL
4111 /****************************************************************************
4113 ****************************************************************************/
4115 void reply_write(struct smb_request *req)
4117 connection_struct *conn = req->conn;
4119 ssize_t nwritten = -1;
4123 struct lock_struct lock;
4125 int saved_errno = 0;
4127 START_PROFILE(SMBwrite);
4130 END_PROFILE(SMBwrite);
4131 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4135 /* If it's an IPC, pass off the pipe handler. */
4137 reply_pipe_write(req);
4138 END_PROFILE(SMBwrite);
4142 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4144 if (!check_fsp(conn, req, fsp)) {
4145 END_PROFILE(SMBwrite);
4149 if (!CHECK_WRITE(fsp)) {
4150 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4151 END_PROFILE(SMBwrite);
4155 numtowrite = SVAL(req->vwv+1, 0);
4156 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4157 data = (const char *)req->buf + 3;
4159 if (!fsp->print_file) {
4160 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4161 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4164 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4165 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4166 END_PROFILE(SMBwrite);
4172 * X/Open SMB protocol says that if smb_vwv1 is
4173 * zero then the file size should be extended or
4174 * truncated to the size given in smb_vwv[2-3].
4177 if(numtowrite == 0) {
4179 * This is actually an allocate call, and set EOF. JRA.
4181 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4183 reply_nterror(req, NT_STATUS_DISK_FULL);
4186 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4188 reply_nterror(req, NT_STATUS_DISK_FULL);
4191 trigger_write_time_update_immediate(fsp);
4193 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4196 status = sync_file(conn, fsp, False);
4197 if (!NT_STATUS_IS_OK(status)) {
4198 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4199 fsp_str_dbg(fsp), nt_errstr(status)));
4200 reply_nterror(req, status);
4205 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4209 if((nwritten == 0) && (numtowrite != 0)) {
4210 reply_nterror(req, NT_STATUS_DISK_FULL);
4214 reply_outbuf(req, 1, 0);
4216 SSVAL(req->outbuf,smb_vwv0,nwritten);
4218 if (nwritten < (ssize_t)numtowrite) {
4219 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4220 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4223 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4226 if (!fsp->print_file) {
4227 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4230 END_PROFILE(SMBwrite);
4234 /****************************************************************************
4235 Ensure a buffer is a valid writeX for recvfile purposes.
4236 ****************************************************************************/
4238 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4239 (2*14) + /* word count (including bcc) */ \
4242 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4245 connection_struct *conn = NULL;
4246 unsigned int doff = 0;
4247 size_t len = smb_len_large(inbuf);
4248 struct smbd_server_connection *sconn = smbd_server_conn;
4250 if (is_encrypted_packet(inbuf)) {
4251 /* Can't do this on encrypted
4256 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4260 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4261 CVAL(inbuf,smb_wct) != 14) {
4262 DEBUG(10,("is_valid_writeX_buffer: chained or "
4263 "invalid word length.\n"));
4267 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4269 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4273 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4276 if (IS_PRINT(conn)) {
4277 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4280 doff = SVAL(inbuf,smb_vwv11);
4282 numtowrite = SVAL(inbuf,smb_vwv10);
4284 if (len > doff && len - doff > 0xFFFF) {
4285 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4288 if (numtowrite == 0) {
4289 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4293 /* Ensure the sizes match up. */
4294 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4295 /* no pad byte...old smbclient :-( */
4296 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4298 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4302 if (len - doff != numtowrite) {
4303 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4304 "len = %u, doff = %u, numtowrite = %u\n",
4307 (unsigned int)numtowrite ));
4311 DEBUG(10,("is_valid_writeX_buffer: true "
4312 "len = %u, doff = %u, numtowrite = %u\n",
4315 (unsigned int)numtowrite ));
4320 /****************************************************************************
4321 Reply to a write and X.
4322 ****************************************************************************/
4324 void reply_write_and_X(struct smb_request *req)
4326 connection_struct *conn = req->conn;
4328 struct lock_struct lock;
4333 unsigned int smb_doff;
4334 unsigned int smblen;
4337 int saved_errno = 0;
4339 START_PROFILE(SMBwriteX);
4341 if ((req->wct != 12) && (req->wct != 14)) {
4342 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4343 END_PROFILE(SMBwriteX);
4347 numtowrite = SVAL(req->vwv+10, 0);
4348 smb_doff = SVAL(req->vwv+11, 0);
4349 smblen = smb_len(req->inbuf);
4351 if (req->unread_bytes > 0xFFFF ||
4352 (smblen > smb_doff &&
4353 smblen - smb_doff > 0xFFFF)) {
4354 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4357 if (req->unread_bytes) {
4358 /* Can't do a recvfile write on IPC$ */
4360 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4361 END_PROFILE(SMBwriteX);
4364 if (numtowrite != req->unread_bytes) {
4365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4366 END_PROFILE(SMBwriteX);
4370 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4371 smb_doff + numtowrite > smblen) {
4372 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4373 END_PROFILE(SMBwriteX);
4378 /* If it's an IPC, pass off the pipe handler. */
4380 if (req->unread_bytes) {
4381 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4382 END_PROFILE(SMBwriteX);
4385 reply_pipe_write_and_X(req);
4386 END_PROFILE(SMBwriteX);
4390 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4391 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4392 write_through = BITSETW(req->vwv+7,0);
4394 if (!check_fsp(conn, req, fsp)) {
4395 END_PROFILE(SMBwriteX);
4399 if (!CHECK_WRITE(fsp)) {
4400 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4401 END_PROFILE(SMBwriteX);
4405 data = smb_base(req->inbuf) + smb_doff;
4407 if(req->wct == 14) {
4408 #ifdef LARGE_SMB_OFF_T
4410 * This is a large offset (64 bit) write.
4412 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4414 #else /* !LARGE_SMB_OFF_T */
4417 * Ensure we haven't been sent a >32 bit offset.
4420 if(IVAL(req->vwv+12, 0) != 0) {
4421 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4422 "used and we don't support 64 bit offsets.\n",
4423 (unsigned int)IVAL(req->vwv+12, 0) ));
4424 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4425 END_PROFILE(SMBwriteX);
4429 #endif /* LARGE_SMB_OFF_T */
4432 /* X/Open SMB protocol says that, unlike SMBwrite
4433 if the length is zero then NO truncation is
4434 done, just a write of zero. To truncate a file,
4437 if(numtowrite == 0) {
4440 if (req->unread_bytes == 0) {
4441 status = schedule_aio_write_and_X(conn,
4448 if (NT_STATUS_IS_OK(status)) {
4449 /* write scheduled - we're done. */
4452 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4453 /* Real error - report to client. */
4454 reply_nterror(req, status);
4457 /* NT_STATUS_RETRY - fall through to sync write. */
4460 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4461 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4464 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4465 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4469 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4470 saved_errno = errno;
4472 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4476 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4480 if((nwritten == 0) && (numtowrite != 0)) {
4481 reply_nterror(req, NT_STATUS_DISK_FULL);
4485 reply_outbuf(req, 6, 0);
4486 SSVAL(req->outbuf,smb_vwv2,nwritten);
4487 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4489 if (nwritten < (ssize_t)numtowrite) {
4490 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4491 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4494 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4495 fsp->fnum, (int)numtowrite, (int)nwritten));
4497 status = sync_file(conn, fsp, write_through);
4498 if (!NT_STATUS_IS_OK(status)) {
4499 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4500 fsp_str_dbg(fsp), nt_errstr(status)));
4501 reply_nterror(req, status);
4505 END_PROFILE(SMBwriteX);
4510 END_PROFILE(SMBwriteX);
4514 /****************************************************************************
4516 ****************************************************************************/
4518 void reply_lseek(struct smb_request *req)
4520 connection_struct *conn = req->conn;
4526 START_PROFILE(SMBlseek);
4529 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4530 END_PROFILE(SMBlseek);
4534 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4536 if (!check_fsp(conn, req, fsp)) {
4540 flush_write_cache(fsp, SEEK_FLUSH);
4542 mode = SVAL(req->vwv+1, 0) & 3;
4543 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4544 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4553 res = fsp->fh->pos + startpos;
4564 if (umode == SEEK_END) {
4565 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4566 if(errno == EINVAL) {
4567 SMB_OFF_T current_pos = startpos;
4569 if(fsp_stat(fsp) == -1) {
4571 map_nt_error_from_unix(errno));
4572 END_PROFILE(SMBlseek);
4576 current_pos += fsp->fsp_name->st.st_ex_size;
4578 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4583 reply_nterror(req, map_nt_error_from_unix(errno));
4584 END_PROFILE(SMBlseek);
4591 reply_outbuf(req, 2, 0);
4592 SIVAL(req->outbuf,smb_vwv0,res);
4594 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4595 fsp->fnum, (double)startpos, (double)res, mode));
4597 END_PROFILE(SMBlseek);
4601 /****************************************************************************
4603 ****************************************************************************/
4605 void reply_flush(struct smb_request *req)
4607 connection_struct *conn = req->conn;
4611 START_PROFILE(SMBflush);
4614 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4618 fnum = SVAL(req->vwv+0, 0);
4619 fsp = file_fsp(req, fnum);
4621 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4626 file_sync_all(conn);
4628 NTSTATUS status = sync_file(conn, fsp, True);
4629 if (!NT_STATUS_IS_OK(status)) {
4630 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4631 fsp_str_dbg(fsp), nt_errstr(status)));
4632 reply_nterror(req, status);
4633 END_PROFILE(SMBflush);
4638 reply_outbuf(req, 0, 0);
4640 DEBUG(3,("flush\n"));
4641 END_PROFILE(SMBflush);
4645 /****************************************************************************
4647 conn POINTER CAN BE NULL HERE !
4648 ****************************************************************************/
4650 void reply_exit(struct smb_request *req)
4652 START_PROFILE(SMBexit);
4654 file_close_pid(req->smbpid, req->vuid);
4656 reply_outbuf(req, 0, 0);
4658 DEBUG(3,("exit\n"));
4660 END_PROFILE(SMBexit);
4664 /****************************************************************************
4665 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4666 ****************************************************************************/
4668 void reply_close(struct smb_request *req)
4670 connection_struct *conn = req->conn;
4671 NTSTATUS status = NT_STATUS_OK;
4672 files_struct *fsp = NULL;
4673 START_PROFILE(SMBclose);
4676 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4677 END_PROFILE(SMBclose);
4681 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4684 * We can only use check_fsp if we know it's not a directory.
4687 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4688 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4689 END_PROFILE(SMBclose);
4693 if(fsp->is_directory) {
4695 * Special case - close NT SMB directory handle.
4697 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4698 status = close_file(req, fsp, NORMAL_CLOSE);
4702 * Close ordinary file.
4705 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4706 fsp->fh->fd, fsp->fnum,
4707 conn->num_files_open));
4710 * Take care of any time sent in the close.
4713 t = srv_make_unix_date3(req->vwv+1);
4714 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4717 * close_file() returns the unix errno if an error
4718 * was detected on close - normally this is due to
4719 * a disk full error. If not then it was probably an I/O error.
4722 status = close_file(req, fsp, NORMAL_CLOSE);
4725 if (!NT_STATUS_IS_OK(status)) {
4726 reply_nterror(req, status);
4727 END_PROFILE(SMBclose);
4731 reply_outbuf(req, 0, 0);
4732 END_PROFILE(SMBclose);
4736 /****************************************************************************
4737 Reply to a writeclose (Core+ protocol).
4738 ****************************************************************************/
4740 void reply_writeclose(struct smb_request *req)
4742 connection_struct *conn = req->conn;
4744 ssize_t nwritten = -1;
4745 NTSTATUS close_status = NT_STATUS_OK;
4748 struct timespec mtime;
4750 struct lock_struct lock;
4752 START_PROFILE(SMBwriteclose);
4755 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4756 END_PROFILE(SMBwriteclose);
4760 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4762 if (!check_fsp(conn, req, fsp)) {
4763 END_PROFILE(SMBwriteclose);
4766 if (!CHECK_WRITE(fsp)) {
4767 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4768 END_PROFILE(SMBwriteclose);
4772 numtowrite = SVAL(req->vwv+1, 0);
4773 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4774 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4775 data = (const char *)req->buf + 1;
4777 if (!fsp->print_file) {
4778 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4779 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4782 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4783 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4784 END_PROFILE(SMBwriteclose);
4789 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4791 set_close_write_time(fsp, mtime);
4794 * More insanity. W2K only closes the file if writelen > 0.
4799 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4800 "file %s\n", fsp_str_dbg(fsp)));
4801 close_status = close_file(req, fsp, NORMAL_CLOSE);
4804 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4805 fsp->fnum, (int)numtowrite, (int)nwritten,
4806 conn->num_files_open));
4808 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4809 reply_nterror(req, NT_STATUS_DISK_FULL);
4813 if(!NT_STATUS_IS_OK(close_status)) {
4814 reply_nterror(req, close_status);
4818 reply_outbuf(req, 1, 0);
4820 SSVAL(req->outbuf,smb_vwv0,nwritten);
4823 if (numtowrite && !fsp->print_file) {
4824 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4827 END_PROFILE(SMBwriteclose);
4832 #define DBGC_CLASS DBGC_LOCKING
4834 /****************************************************************************
4836 ****************************************************************************/
4838 void reply_lock(struct smb_request *req)
4840 connection_struct *conn = req->conn;
4841 uint64_t count,offset;
4844 struct byte_range_lock *br_lck = NULL;
4846 START_PROFILE(SMBlock);
4849 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4850 END_PROFILE(SMBlock);
4854 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4856 if (!check_fsp(conn, req, fsp)) {
4857 END_PROFILE(SMBlock);
4861 count = (uint64_t)IVAL(req->vwv+1, 0);
4862 offset = (uint64_t)IVAL(req->vwv+3, 0);
4864 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4865 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4867 br_lck = do_lock(smbd_messaging_context(),
4869 (uint64_t)req->smbpid,
4874 False, /* Non-blocking lock. */
4879 TALLOC_FREE(br_lck);
4881 if (NT_STATUS_V(status)) {
4882 reply_nterror(req, status);
4883 END_PROFILE(SMBlock);
4887 reply_outbuf(req, 0, 0);
4889 END_PROFILE(SMBlock);
4893 /****************************************************************************
4895 ****************************************************************************/
4897 void reply_unlock(struct smb_request *req)
4899 connection_struct *conn = req->conn;
4900 uint64_t count,offset;
4904 START_PROFILE(SMBunlock);
4907 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4908 END_PROFILE(SMBunlock);
4912 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4914 if (!check_fsp(conn, req, fsp)) {
4915 END_PROFILE(SMBunlock);
4919 count = (uint64_t)IVAL(req->vwv+1, 0);
4920 offset = (uint64_t)IVAL(req->vwv+3, 0);
4922 status = do_unlock(smbd_messaging_context(),
4924 (uint64_t)req->smbpid,
4929 if (NT_STATUS_V(status)) {
4930 reply_nterror(req, status);
4931 END_PROFILE(SMBunlock);
4935 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4936 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4938 reply_outbuf(req, 0, 0);
4940 END_PROFILE(SMBunlock);
4945 #define DBGC_CLASS DBGC_ALL
4947 /****************************************************************************
4949 conn POINTER CAN BE NULL HERE !
4950 ****************************************************************************/
4952 void reply_tdis(struct smb_request *req)
4954 connection_struct *conn = req->conn;
4955 START_PROFILE(SMBtdis);
4958 DEBUG(4,("Invalid connection in tdis\n"));
4959 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
4960 END_PROFILE(SMBtdis);
4966 close_cnum(conn,req->vuid);
4969 reply_outbuf(req, 0, 0);
4970 END_PROFILE(SMBtdis);
4974 /****************************************************************************
4976 conn POINTER CAN BE NULL HERE !
4977 ****************************************************************************/
4979 void reply_echo(struct smb_request *req)
4981 connection_struct *conn = req->conn;
4982 struct smb_perfcount_data local_pcd;
4983 struct smb_perfcount_data *cur_pcd;
4987 START_PROFILE(SMBecho);
4989 smb_init_perfcount_data(&local_pcd);
4992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4993 END_PROFILE(SMBecho);
4997 smb_reverb = SVAL(req->vwv+0, 0);
4999 reply_outbuf(req, 1, req->buflen);
5001 /* copy any incoming data back out */
5002 if (req->buflen > 0) {
5003 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5006 if (smb_reverb > 100) {
5007 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5011 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5013 /* this makes sure we catch the request pcd */
5014 if (seq_num == smb_reverb) {
5015 cur_pcd = &req->pcd;
5017 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5018 cur_pcd = &local_pcd;
5021 SSVAL(req->outbuf,smb_vwv0,seq_num);
5023 show_msg((char *)req->outbuf);
5024 if (!srv_send_smb(smbd_server_fd(),
5025 (char *)req->outbuf,
5026 true, req->seqnum+1,
5027 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5029 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5032 DEBUG(3,("echo %d times\n", smb_reverb));
5034 TALLOC_FREE(req->outbuf);
5036 END_PROFILE(SMBecho);
5040 /****************************************************************************
5041 Reply to a printopen.
5042 ****************************************************************************/
5044 void reply_printopen(struct smb_request *req)
5046 connection_struct *conn = req->conn;
5050 START_PROFILE(SMBsplopen);
5053 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5054 END_PROFILE(SMBsplopen);
5058 if (!CAN_PRINT(conn)) {
5059 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5060 END_PROFILE(SMBsplopen);
5064 status = file_new(req, conn, &fsp);
5065 if(!NT_STATUS_IS_OK(status)) {
5066 reply_nterror(req, status);
5067 END_PROFILE(SMBsplopen);
5071 /* Open for exclusive use, write only. */
5072 status = print_fsp_open(req, conn, NULL, req->vuid, fsp);
5074 if (!NT_STATUS_IS_OK(status)) {
5075 file_free(req, fsp);
5076 reply_nterror(req, status);
5077 END_PROFILE(SMBsplopen);
5081 reply_outbuf(req, 1, 0);
5082 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5084 DEBUG(3,("openprint fd=%d fnum=%d\n",
5085 fsp->fh->fd, fsp->fnum));
5087 END_PROFILE(SMBsplopen);
5091 /****************************************************************************
5092 Reply to a printclose.
5093 ****************************************************************************/
5095 void reply_printclose(struct smb_request *req)
5097 connection_struct *conn = req->conn;
5101 START_PROFILE(SMBsplclose);
5104 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5105 END_PROFILE(SMBsplclose);
5109 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5111 if (!check_fsp(conn, req, fsp)) {
5112 END_PROFILE(SMBsplclose);
5116 if (!CAN_PRINT(conn)) {
5117 reply_force_doserror(req, ERRSRV, ERRerror);
5118 END_PROFILE(SMBsplclose);
5122 DEBUG(3,("printclose fd=%d fnum=%d\n",
5123 fsp->fh->fd,fsp->fnum));
5125 status = close_file(req, fsp, NORMAL_CLOSE);
5127 if(!NT_STATUS_IS_OK(status)) {
5128 reply_nterror(req, status);
5129 END_PROFILE(SMBsplclose);
5133 reply_outbuf(req, 0, 0);
5135 END_PROFILE(SMBsplclose);
5139 /****************************************************************************
5140 Reply to a printqueue.
5141 ****************************************************************************/
5143 void reply_printqueue(struct smb_request *req)
5145 connection_struct *conn = req->conn;
5149 START_PROFILE(SMBsplretq);
5152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5153 END_PROFILE(SMBsplretq);
5157 max_count = SVAL(req->vwv+0, 0);
5158 start_index = SVAL(req->vwv+1, 0);
5160 /* we used to allow the client to get the cnum wrong, but that
5161 is really quite gross and only worked when there was only
5162 one printer - I think we should now only accept it if they
5163 get it right (tridge) */
5164 if (!CAN_PRINT(conn)) {
5165 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5166 END_PROFILE(SMBsplretq);
5170 reply_outbuf(req, 2, 3);
5171 SSVAL(req->outbuf,smb_vwv0,0);
5172 SSVAL(req->outbuf,smb_vwv1,0);
5173 SCVAL(smb_buf(req->outbuf),0,1);
5174 SSVAL(smb_buf(req->outbuf),1,0);
5176 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5177 start_index, max_count));
5180 print_queue_struct *queue = NULL;
5181 print_status_struct status;
5182 int count = print_queue_status(SNUM(conn), &queue, &status);
5183 int num_to_get = ABS(max_count);
5184 int first = (max_count>0?start_index:start_index+max_count+1);
5190 num_to_get = MIN(num_to_get,count-first);
5193 for (i=first;i<first+num_to_get;i++) {
5197 srv_put_dos_date2(p,0,queue[i].time);
5198 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5199 SSVAL(p,5, queue[i].job);
5200 SIVAL(p,7,queue[i].size);
5202 srvstr_push(blob, req->flags2, p+12,
5203 queue[i].fs_user, 16, STR_ASCII);
5205 if (message_push_blob(
5208 blob, sizeof(blob))) == -1) {
5209 reply_nterror(req, NT_STATUS_NO_MEMORY);
5210 END_PROFILE(SMBsplretq);
5216 SSVAL(req->outbuf,smb_vwv0,count);
5217 SSVAL(req->outbuf,smb_vwv1,
5218 (max_count>0?first+count:first-1));
5219 SCVAL(smb_buf(req->outbuf),0,1);
5220 SSVAL(smb_buf(req->outbuf),1,28*count);
5225 DEBUG(3,("%d entries returned in queue\n",count));
5228 END_PROFILE(SMBsplretq);
5232 /****************************************************************************
5233 Reply to a printwrite.
5234 ****************************************************************************/
5236 void reply_printwrite(struct smb_request *req)
5238 connection_struct *conn = req->conn;
5243 START_PROFILE(SMBsplwr);
5246 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5247 END_PROFILE(SMBsplwr);
5251 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5253 if (!check_fsp(conn, req, fsp)) {
5254 END_PROFILE(SMBsplwr);
5258 if (!CAN_PRINT(conn)) {
5259 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5260 END_PROFILE(SMBsplwr);
5264 if (!CHECK_WRITE(fsp)) {
5265 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5266 END_PROFILE(SMBsplwr);
5270 numtowrite = SVAL(req->buf, 1);
5272 if (req->buflen < numtowrite + 3) {
5273 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5274 END_PROFILE(SMBsplwr);
5278 data = (const char *)req->buf + 3;
5280 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5281 reply_nterror(req, map_nt_error_from_unix(errno));
5282 END_PROFILE(SMBsplwr);
5286 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5288 END_PROFILE(SMBsplwr);
5292 /****************************************************************************
5294 ****************************************************************************/
5296 void reply_mkdir(struct smb_request *req)
5298 connection_struct *conn = req->conn;
5299 struct smb_filename *smb_dname = NULL;
5300 char *directory = NULL;
5302 TALLOC_CTX *ctx = talloc_tos();
5304 START_PROFILE(SMBmkdir);
5306 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5307 STR_TERMINATE, &status);
5308 if (!NT_STATUS_IS_OK(status)) {
5309 reply_nterror(req, status);
5313 status = filename_convert(ctx, conn,
5314 req->flags2 & FLAGS2_DFS_PATHNAMES,
5319 if (!NT_STATUS_IS_OK(status)) {
5320 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5321 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5322 ERRSRV, ERRbadpath);
5325 reply_nterror(req, status);
5329 status = create_directory(conn, req, smb_dname);
5331 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5333 if (!NT_STATUS_IS_OK(status)) {
5335 if (!use_nt_status()
5336 && NT_STATUS_EQUAL(status,
5337 NT_STATUS_OBJECT_NAME_COLLISION)) {
5339 * Yes, in the DOS error code case we get a
5340 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5341 * samba4 torture test.
5343 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5346 reply_nterror(req, status);
5350 reply_outbuf(req, 0, 0);
5352 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5354 TALLOC_FREE(smb_dname);
5355 END_PROFILE(SMBmkdir);
5359 /****************************************************************************
5361 ****************************************************************************/
5363 void reply_rmdir(struct smb_request *req)
5365 connection_struct *conn = req->conn;
5366 struct smb_filename *smb_dname = NULL;
5367 char *directory = NULL;
5369 TALLOC_CTX *ctx = talloc_tos();
5370 files_struct *fsp = NULL;
5372 struct smbd_server_connection *sconn = smbd_server_conn;
5374 START_PROFILE(SMBrmdir);
5376 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5377 STR_TERMINATE, &status);
5378 if (!NT_STATUS_IS_OK(status)) {
5379 reply_nterror(req, status);
5383 status = filename_convert(ctx, conn,
5384 req->flags2 & FLAGS2_DFS_PATHNAMES,
5389 if (!NT_STATUS_IS_OK(status)) {
5390 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5391 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5392 ERRSRV, ERRbadpath);
5395 reply_nterror(req, status);
5399 if (is_ntfs_stream_smb_fname(smb_dname)) {
5400 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5404 status = SMB_VFS_CREATE_FILE(
5407 0, /* root_dir_fid */
5408 smb_dname, /* fname */
5409 DELETE_ACCESS, /* access_mask */
5410 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5412 FILE_OPEN, /* create_disposition*/
5413 FILE_DIRECTORY_FILE, /* create_options */
5414 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5415 0, /* oplock_request */
5416 0, /* allocation_size */
5417 0, /* private_flags */
5423 if (!NT_STATUS_IS_OK(status)) {
5424 if (open_was_deferred(req->mid)) {
5425 /* We have re-scheduled this call. */
5428 reply_nterror(req, status);
5432 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5433 if (!NT_STATUS_IS_OK(status)) {
5434 close_file(req, fsp, ERROR_CLOSE);
5435 reply_nterror(req, status);
5439 if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
5440 close_file(req, fsp, ERROR_CLOSE);
5441 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5445 status = close_file(req, fsp, NORMAL_CLOSE);
5446 if (!NT_STATUS_IS_OK(status)) {
5447 reply_nterror(req, status);
5449 reply_outbuf(req, 0, 0);
5452 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5454 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5456 TALLOC_FREE(smb_dname);
5457 END_PROFILE(SMBrmdir);
5461 /*******************************************************************
5462 Resolve wildcards in a filename rename.
5463 ********************************************************************/
5465 static bool resolve_wildcards(TALLOC_CTX *ctx,
5470 char *name2_copy = NULL;
5475 char *p,*p2, *pname1, *pname2;
5477 name2_copy = talloc_strdup(ctx, name2);
5482 pname1 = strrchr_m(name1,'/');
5483 pname2 = strrchr_m(name2_copy,'/');
5485 if (!pname1 || !pname2) {
5489 /* Truncate the copy of name2 at the last '/' */
5492 /* Now go past the '/' */
5496 root1 = talloc_strdup(ctx, pname1);
5497 root2 = talloc_strdup(ctx, pname2);
5499 if (!root1 || !root2) {
5503 p = strrchr_m(root1,'.');
5506 ext1 = talloc_strdup(ctx, p+1);
5508 ext1 = talloc_strdup(ctx, "");
5510 p = strrchr_m(root2,'.');
5513 ext2 = talloc_strdup(ctx, p+1);
5515 ext2 = talloc_strdup(ctx, "");
5518 if (!ext1 || !ext2) {
5526 /* Hmmm. Should this be mb-aware ? */
5529 } else if (*p2 == '*') {
5531 root2 = talloc_asprintf(ctx, "%s%s",
5550 /* Hmmm. Should this be mb-aware ? */
5553 } else if (*p2 == '*') {
5555 ext2 = talloc_asprintf(ctx, "%s%s",
5571 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5576 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5588 /****************************************************************************
5589 Ensure open files have their names updated. Updated to notify other smbd's
5591 ****************************************************************************/
5593 static void rename_open_files(connection_struct *conn,
5594 struct share_mode_lock *lck,
5595 const struct smb_filename *smb_fname_dst)
5598 bool did_rename = False;
5601 for(fsp = file_find_di_first(lck->id); fsp;
5602 fsp = file_find_di_next(fsp)) {
5603 /* fsp_name is a relative path under the fsp. To change this for other
5604 sharepaths we need to manipulate relative paths. */
5605 /* TODO - create the absolute path and manipulate the newname
5606 relative to the sharepath. */
5607 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5610 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5611 "(file_id %s) from %s -> %s\n", fsp->fnum,
5612 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5613 smb_fname_str_dbg(smb_fname_dst)));
5615 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5616 if (NT_STATUS_IS_OK(status)) {
5622 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5623 "for %s\n", file_id_string_tos(&lck->id),
5624 smb_fname_str_dbg(smb_fname_dst)));
5627 /* Send messages to all smbd's (not ourself) that the name has changed. */
5628 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5633 /****************************************************************************
5634 We need to check if the source path is a parent directory of the destination
5635 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5636 refuse the rename with a sharing violation. Under UNIX the above call can
5637 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5638 probably need to check that the client is a Windows one before disallowing
5639 this as a UNIX client (one with UNIX extensions) can know the source is a
5640 symlink and make this decision intelligently. Found by an excellent bug
5641 report from <AndyLiebman@aol.com>.
5642 ****************************************************************************/
5644 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5645 const struct smb_filename *smb_fname_dst)
5647 const char *psrc = smb_fname_src->base_name;
5648 const char *pdst = smb_fname_dst->base_name;
5651 if (psrc[0] == '.' && psrc[1] == '/') {
5654 if (pdst[0] == '.' && pdst[1] == '/') {
5657 if ((slen = strlen(psrc)) > strlen(pdst)) {
5660 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5664 * Do the notify calls from a rename
5667 static void notify_rename(connection_struct *conn, bool is_dir,
5668 const struct smb_filename *smb_fname_src,
5669 const struct smb_filename *smb_fname_dst)
5671 char *parent_dir_src = NULL;
5672 char *parent_dir_dst = NULL;
5675 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5676 : FILE_NOTIFY_CHANGE_FILE_NAME;
5678 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5679 &parent_dir_src, NULL) ||
5680 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5681 &parent_dir_dst, NULL)) {
5685 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5686 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5687 smb_fname_src->base_name);
5688 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5689 smb_fname_dst->base_name);
5692 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5693 smb_fname_src->base_name);
5694 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5695 smb_fname_dst->base_name);
5698 /* this is a strange one. w2k3 gives an additional event for
5699 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5700 files, but not directories */
5702 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5703 FILE_NOTIFY_CHANGE_ATTRIBUTES
5704 |FILE_NOTIFY_CHANGE_CREATION,
5705 smb_fname_dst->base_name);
5708 TALLOC_FREE(parent_dir_src);
5709 TALLOC_FREE(parent_dir_dst);
5712 /****************************************************************************
5713 Rename an open file - given an fsp.
5714 ****************************************************************************/
5716 NTSTATUS rename_internals_fsp(connection_struct *conn,
5718 const struct smb_filename *smb_fname_dst_in,
5720 bool replace_if_exists)
5722 TALLOC_CTX *ctx = talloc_tos();
5723 struct smb_filename *smb_fname_dst = NULL;
5724 NTSTATUS status = NT_STATUS_OK;
5725 struct share_mode_lock *lck = NULL;
5726 bool dst_exists, old_is_stream, new_is_stream;
5728 status = check_name(conn, smb_fname_dst_in->base_name);
5729 if (!NT_STATUS_IS_OK(status)) {
5733 /* Make a copy of the dst smb_fname structs */
5735 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5736 if (!NT_STATUS_IS_OK(status)) {
5740 /* Ensure the dst smb_fname contains a '/' */
5741 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5743 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5744 smb_fname_dst->base_name);
5746 status = NT_STATUS_NO_MEMORY;
5749 TALLOC_FREE(smb_fname_dst->base_name);
5750 smb_fname_dst->base_name = tmp;
5754 * Check for special case with case preserving and not
5755 * case sensitive. If the old last component differs from the original
5756 * last component only by case, then we should allow
5757 * the rename (user is trying to change the case of the
5760 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5761 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5762 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5764 char *fname_dst_lcomp_base_mod = NULL;
5765 struct smb_filename *smb_fname_orig_lcomp = NULL;
5768 * Get the last component of the destination name. Note that
5769 * we guarantee that destination name contains a '/' character
5772 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5773 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5774 if (!fname_dst_lcomp_base_mod) {
5775 status = NT_STATUS_NO_MEMORY;
5780 * Create an smb_filename struct using the original last
5781 * component of the destination.
5783 status = create_synthetic_smb_fname_split(ctx,
5784 smb_fname_dst->original_lcomp, NULL,
5785 &smb_fname_orig_lcomp);
5786 if (!NT_STATUS_IS_OK(status)) {
5787 TALLOC_FREE(fname_dst_lcomp_base_mod);
5791 /* If the base names only differ by case, use original. */
5792 if(!strcsequal(fname_dst_lcomp_base_mod,
5793 smb_fname_orig_lcomp->base_name)) {
5796 * Replace the modified last component with the
5799 *last_slash = '\0'; /* Truncate at the '/' */
5800 tmp = talloc_asprintf(smb_fname_dst,
5802 smb_fname_dst->base_name,
5803 smb_fname_orig_lcomp->base_name);
5805 status = NT_STATUS_NO_MEMORY;
5806 TALLOC_FREE(fname_dst_lcomp_base_mod);
5807 TALLOC_FREE(smb_fname_orig_lcomp);
5810 TALLOC_FREE(smb_fname_dst->base_name);
5811 smb_fname_dst->base_name = tmp;
5814 /* If the stream_names only differ by case, use original. */
5815 if(!strcsequal(smb_fname_dst->stream_name,
5816 smb_fname_orig_lcomp->stream_name)) {
5818 /* Use the original stream. */
5819 tmp = talloc_strdup(smb_fname_dst,
5820 smb_fname_orig_lcomp->stream_name);
5822 status = NT_STATUS_NO_MEMORY;
5823 TALLOC_FREE(fname_dst_lcomp_base_mod);
5824 TALLOC_FREE(smb_fname_orig_lcomp);
5827 TALLOC_FREE(smb_fname_dst->stream_name);
5828 smb_fname_dst->stream_name = tmp;
5830 TALLOC_FREE(fname_dst_lcomp_base_mod);
5831 TALLOC_FREE(smb_fname_orig_lcomp);
5835 * If the src and dest names are identical - including case,
5836 * don't do the rename, just return success.
5839 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5840 strcsequal(fsp->fsp_name->stream_name,
5841 smb_fname_dst->stream_name)) {
5842 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5843 "- returning success\n",
5844 smb_fname_str_dbg(smb_fname_dst)));
5845 status = NT_STATUS_OK;
5849 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
5850 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5852 /* Return the correct error code if both names aren't streams. */
5853 if (!old_is_stream && new_is_stream) {
5854 status = NT_STATUS_OBJECT_NAME_INVALID;
5858 if (old_is_stream && !new_is_stream) {
5859 status = NT_STATUS_INVALID_PARAMETER;
5863 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
5865 if(!replace_if_exists && dst_exists) {
5866 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
5867 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5868 smb_fname_str_dbg(smb_fname_dst)));
5869 status = NT_STATUS_OBJECT_NAME_COLLISION;
5874 struct file_id fileid = vfs_file_id_from_sbuf(conn,
5875 &smb_fname_dst->st);
5876 files_struct *dst_fsp = file_find_di_first(fileid);
5877 /* The file can be open when renaming a stream */
5878 if (dst_fsp && !new_is_stream) {
5879 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5880 status = NT_STATUS_ACCESS_DENIED;
5885 /* Ensure we have a valid stat struct for the source. */
5886 status = vfs_stat_fsp(fsp);
5887 if (!NT_STATUS_IS_OK(status)) {
5891 status = can_rename(conn, fsp, attrs);
5893 if (!NT_STATUS_IS_OK(status)) {
5894 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
5895 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
5896 smb_fname_str_dbg(smb_fname_dst)));
5897 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5898 status = NT_STATUS_ACCESS_DENIED;
5902 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
5903 status = NT_STATUS_ACCESS_DENIED;
5906 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5910 * We have the file open ourselves, so not being able to get the
5911 * corresponding share mode lock is a fatal error.
5914 SMB_ASSERT(lck != NULL);
5916 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
5917 uint32 create_options = fsp->fh->private_options;
5919 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
5920 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5921 smb_fname_str_dbg(smb_fname_dst)));
5923 if (lp_map_archive(SNUM(conn)) ||
5924 lp_store_dos_attributes(SNUM(conn))) {
5925 /* We must set the archive bit on the newly
5927 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
5928 uint32_t old_dosmode = dos_mode(conn,
5930 file_set_dosmode(conn,
5932 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
5938 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
5941 rename_open_files(conn, lck, smb_fname_dst);
5944 * A rename acts as a new file create w.r.t. allowing an initial delete
5945 * on close, probably because in Windows there is a new handle to the
5946 * new file. If initial delete on close was requested but not
5947 * originally set, we need to set it here. This is probably not 100% correct,
5948 * but will work for the CIFSFS client which in non-posix mode
5949 * depends on these semantics. JRA.
5952 if (create_options & FILE_DELETE_ON_CLOSE) {
5953 status = can_set_delete_on_close(fsp, 0);
5955 if (NT_STATUS_IS_OK(status)) {
5956 /* Note that here we set the *inital* delete on close flag,
5957 * not the regular one. The magic gets handled in close. */
5958 fsp->initial_delete_on_close = True;
5962 status = NT_STATUS_OK;
5968 if (errno == ENOTDIR || errno == EISDIR) {
5969 status = NT_STATUS_OBJECT_NAME_COLLISION;
5971 status = map_nt_error_from_unix(errno);
5974 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
5975 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
5976 smb_fname_str_dbg(smb_fname_dst)));
5979 TALLOC_FREE(smb_fname_dst);
5984 /****************************************************************************
5985 The guts of the rename command, split out so it may be called by the NT SMB
5987 ****************************************************************************/
5989 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5990 connection_struct *conn,
5991 struct smb_request *req,
5992 struct smb_filename *smb_fname_src,
5993 struct smb_filename *smb_fname_dst,
5995 bool replace_if_exists,
5998 uint32_t access_mask)
6000 char *fname_src_dir = NULL;
6001 char *fname_src_mask = NULL;
6003 NTSTATUS status = NT_STATUS_OK;
6004 struct smb_Dir *dir_hnd = NULL;
6005 const char *dname = NULL;
6006 char *talloced = NULL;
6008 int create_options = 0;
6009 bool posix_pathnames = lp_posix_pathnames();
6012 * Split the old name into directory and last component
6013 * strings. Note that unix_convert may have stripped off a
6014 * leading ./ from both name and newname if the rename is
6015 * at the root of the share. We need to make sure either both
6016 * name and newname contain a / character or neither of them do
6017 * as this is checked in resolve_wildcards().
6020 /* Split up the directory from the filename/mask. */
6021 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6022 &fname_src_dir, &fname_src_mask);
6023 if (!NT_STATUS_IS_OK(status)) {
6024 status = NT_STATUS_NO_MEMORY;
6029 * We should only check the mangled cache
6030 * here if unix_convert failed. This means
6031 * that the path in 'mask' doesn't exist
6032 * on the file system and so we need to look
6033 * for a possible mangle. This patch from
6034 * Tine Smukavec <valentin.smukavec@hermes.si>.
6037 if (!VALID_STAT(smb_fname_src->st) &&
6038 mangle_is_mangled(fname_src_mask, conn->params)) {
6039 char *new_mask = NULL;
6040 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6043 TALLOC_FREE(fname_src_mask);
6044 fname_src_mask = new_mask;
6048 if (!src_has_wild) {
6052 * Only one file needs to be renamed. Append the mask back
6053 * onto the directory.
6055 TALLOC_FREE(smb_fname_src->base_name);
6056 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6060 if (!smb_fname_src->base_name) {
6061 status = NT_STATUS_NO_MEMORY;
6065 /* Ensure dst fname contains a '/' also */
6066 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6068 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6069 smb_fname_dst->base_name);
6071 status = NT_STATUS_NO_MEMORY;
6074 TALLOC_FREE(smb_fname_dst->base_name);
6075 smb_fname_dst->base_name = tmp;
6078 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6079 "case_preserve = %d, short case preserve = %d, "
6080 "directory = %s, newname = %s, "
6081 "last_component_dest = %s\n",
6082 conn->case_sensitive, conn->case_preserve,
6083 conn->short_case_preserve,
6084 smb_fname_str_dbg(smb_fname_src),
6085 smb_fname_str_dbg(smb_fname_dst),
6086 smb_fname_dst->original_lcomp));
6088 /* The dest name still may have wildcards. */
6089 if (dest_has_wild) {
6090 char *fname_dst_mod = NULL;
6091 if (!resolve_wildcards(smb_fname_dst,
6092 smb_fname_src->base_name,
6093 smb_fname_dst->base_name,
6095 DEBUG(6, ("rename_internals: resolve_wildcards "
6097 smb_fname_src->base_name,
6098 smb_fname_dst->base_name));
6099 status = NT_STATUS_NO_MEMORY;
6102 TALLOC_FREE(smb_fname_dst->base_name);
6103 smb_fname_dst->base_name = fname_dst_mod;
6106 ZERO_STRUCT(smb_fname_src->st);
6107 if (posix_pathnames) {
6108 SMB_VFS_LSTAT(conn, smb_fname_src);
6110 SMB_VFS_STAT(conn, smb_fname_src);
6113 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6114 create_options |= FILE_DIRECTORY_FILE;
6117 status = SMB_VFS_CREATE_FILE(
6120 0, /* root_dir_fid */
6121 smb_fname_src, /* fname */
6122 access_mask, /* access_mask */
6123 (FILE_SHARE_READ | /* share_access */
6125 FILE_OPEN, /* create_disposition*/
6126 create_options, /* create_options */
6127 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6128 0, /* oplock_request */
6129 0, /* allocation_size */
6130 0, /* private_flags */
6136 if (!NT_STATUS_IS_OK(status)) {
6137 DEBUG(3, ("Could not open rename source %s: %s\n",
6138 smb_fname_str_dbg(smb_fname_src),
6139 nt_errstr(status)));
6143 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6144 attrs, replace_if_exists);
6146 close_file(req, fsp, NORMAL_CLOSE);
6148 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6149 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6150 smb_fname_str_dbg(smb_fname_dst)));
6156 * Wildcards - process each file that matches.
6158 if (strequal(fname_src_mask, "????????.???")) {
6159 TALLOC_FREE(fname_src_mask);
6160 fname_src_mask = talloc_strdup(ctx, "*");
6161 if (!fname_src_mask) {
6162 status = NT_STATUS_NO_MEMORY;
6167 status = check_name(conn, fname_src_dir);
6168 if (!NT_STATUS_IS_OK(status)) {
6172 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6174 if (dir_hnd == NULL) {
6175 status = map_nt_error_from_unix(errno);
6179 status = NT_STATUS_NO_SUCH_FILE;
6181 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6182 * - gentest fix. JRA
6185 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6187 files_struct *fsp = NULL;
6188 char *destname = NULL;
6189 bool sysdir_entry = False;
6191 /* Quick check for "." and ".." */
6192 if (ISDOT(dname) || ISDOTDOT(dname)) {
6194 sysdir_entry = True;
6196 TALLOC_FREE(talloced);
6201 if (!is_visible_file(conn, fname_src_dir, dname,
6202 &smb_fname_src->st, false)) {
6203 TALLOC_FREE(talloced);
6207 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6208 TALLOC_FREE(talloced);
6213 status = NT_STATUS_OBJECT_NAME_INVALID;
6217 TALLOC_FREE(smb_fname_src->base_name);
6218 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6222 if (!smb_fname_src->base_name) {
6223 status = NT_STATUS_NO_MEMORY;
6227 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6228 smb_fname_dst->base_name,
6230 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6231 smb_fname_src->base_name, destname));
6232 TALLOC_FREE(talloced);
6236 status = NT_STATUS_NO_MEMORY;
6240 TALLOC_FREE(smb_fname_dst->base_name);
6241 smb_fname_dst->base_name = destname;
6243 ZERO_STRUCT(smb_fname_src->st);
6244 if (posix_pathnames) {
6245 SMB_VFS_LSTAT(conn, smb_fname_src);
6247 SMB_VFS_STAT(conn, smb_fname_src);
6252 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6253 create_options |= FILE_DIRECTORY_FILE;
6256 status = SMB_VFS_CREATE_FILE(
6259 0, /* root_dir_fid */
6260 smb_fname_src, /* fname */
6261 access_mask, /* access_mask */
6262 (FILE_SHARE_READ | /* share_access */
6264 FILE_OPEN, /* create_disposition*/
6265 create_options, /* create_options */
6266 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6267 0, /* oplock_request */
6268 0, /* allocation_size */
6269 0, /* private_flags */
6275 if (!NT_STATUS_IS_OK(status)) {
6276 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6277 "returned %s rename %s -> %s\n",
6279 smb_fname_str_dbg(smb_fname_src),
6280 smb_fname_str_dbg(smb_fname_dst)));
6284 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6286 if (!smb_fname_dst->original_lcomp) {
6287 status = NT_STATUS_NO_MEMORY;
6291 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6292 attrs, replace_if_exists);
6294 close_file(req, fsp, NORMAL_CLOSE);
6296 if (!NT_STATUS_IS_OK(status)) {
6297 DEBUG(3, ("rename_internals_fsp returned %s for "
6298 "rename %s -> %s\n", nt_errstr(status),
6299 smb_fname_str_dbg(smb_fname_src),
6300 smb_fname_str_dbg(smb_fname_dst)));
6306 DEBUG(3,("rename_internals: doing rename on %s -> "
6307 "%s\n", smb_fname_str_dbg(smb_fname_src),
6308 smb_fname_str_dbg(smb_fname_src)));
6309 TALLOC_FREE(talloced);
6311 TALLOC_FREE(dir_hnd);
6313 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6314 status = map_nt_error_from_unix(errno);
6318 TALLOC_FREE(talloced);
6319 TALLOC_FREE(fname_src_dir);
6320 TALLOC_FREE(fname_src_mask);
6324 /****************************************************************************
6326 ****************************************************************************/
6328 void reply_mv(struct smb_request *req)
6330 connection_struct *conn = req->conn;
6332 char *newname = NULL;
6336 bool src_has_wcard = False;
6337 bool dest_has_wcard = False;
6338 TALLOC_CTX *ctx = talloc_tos();
6339 struct smb_filename *smb_fname_src = NULL;
6340 struct smb_filename *smb_fname_dst = NULL;
6342 START_PROFILE(SMBmv);
6345 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6349 attrs = SVAL(req->vwv+0, 0);
6351 p = (const char *)req->buf + 1;
6352 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6353 &status, &src_has_wcard);
6354 if (!NT_STATUS_IS_OK(status)) {
6355 reply_nterror(req, status);
6359 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6360 &status, &dest_has_wcard);
6361 if (!NT_STATUS_IS_OK(status)) {
6362 reply_nterror(req, status);
6366 status = filename_convert(ctx,
6368 req->flags2 & FLAGS2_DFS_PATHNAMES,
6370 UCF_COND_ALLOW_WCARD_LCOMP,
6374 if (!NT_STATUS_IS_OK(status)) {
6375 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6376 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6377 ERRSRV, ERRbadpath);
6380 reply_nterror(req, status);
6384 status = filename_convert(ctx,
6386 req->flags2 & FLAGS2_DFS_PATHNAMES,
6388 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6392 if (!NT_STATUS_IS_OK(status)) {
6393 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6394 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6395 ERRSRV, ERRbadpath);
6398 reply_nterror(req, status);
6402 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6403 smb_fname_str_dbg(smb_fname_dst)));
6405 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6406 attrs, False, src_has_wcard, dest_has_wcard,
6408 if (!NT_STATUS_IS_OK(status)) {
6409 if (open_was_deferred(req->mid)) {
6410 /* We have re-scheduled this call. */
6413 reply_nterror(req, status);
6417 reply_outbuf(req, 0, 0);
6419 TALLOC_FREE(smb_fname_src);
6420 TALLOC_FREE(smb_fname_dst);
6425 /*******************************************************************
6426 Copy a file as part of a reply_copy.
6427 ******************************************************************/
6430 * TODO: check error codes on all callers
6433 NTSTATUS copy_file(TALLOC_CTX *ctx,
6434 connection_struct *conn,
6435 struct smb_filename *smb_fname_src,
6436 struct smb_filename *smb_fname_dst,
6439 bool target_is_directory)
6441 struct smb_filename *smb_fname_dst_tmp = NULL;
6443 files_struct *fsp1,*fsp2;
6445 uint32 new_create_disposition;
6449 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6450 if (!NT_STATUS_IS_OK(status)) {
6455 * If the target is a directory, extract the last component from the
6456 * src filename and append it to the dst filename
6458 if (target_is_directory) {
6461 /* dest/target can't be a stream if it's a directory. */
6462 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6464 p = strrchr_m(smb_fname_src->base_name,'/');
6468 p = smb_fname_src->base_name;
6470 smb_fname_dst_tmp->base_name =
6471 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6473 if (!smb_fname_dst_tmp->base_name) {
6474 status = NT_STATUS_NO_MEMORY;
6479 status = vfs_file_exist(conn, smb_fname_src);
6480 if (!NT_STATUS_IS_OK(status)) {
6484 if (!target_is_directory && count) {
6485 new_create_disposition = FILE_OPEN;
6487 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6489 &new_create_disposition,
6492 status = NT_STATUS_INVALID_PARAMETER;
6497 /* Open the src file for reading. */
6498 status = SMB_VFS_CREATE_FILE(
6501 0, /* root_dir_fid */
6502 smb_fname_src, /* fname */
6503 FILE_GENERIC_READ, /* access_mask */
6504 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6505 FILE_OPEN, /* create_disposition*/
6506 0, /* create_options */
6507 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6508 INTERNAL_OPEN_ONLY, /* oplock_request */
6509 0, /* allocation_size */
6510 0, /* private_flags */
6516 if (!NT_STATUS_IS_OK(status)) {
6520 dosattrs = dos_mode(conn, smb_fname_src);
6522 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6523 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6526 /* Open the dst file for writing. */
6527 status = SMB_VFS_CREATE_FILE(
6530 0, /* root_dir_fid */
6531 smb_fname_dst, /* fname */
6532 FILE_GENERIC_WRITE, /* access_mask */
6533 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6534 new_create_disposition, /* create_disposition*/
6535 0, /* create_options */
6536 dosattrs, /* file_attributes */
6537 INTERNAL_OPEN_ONLY, /* oplock_request */
6538 0, /* allocation_size */
6539 0, /* private_flags */
6545 if (!NT_STATUS_IS_OK(status)) {
6546 close_file(NULL, fsp1, ERROR_CLOSE);
6550 if ((ofun&3) == 1) {
6551 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6552 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6554 * Stop the copy from occurring.
6557 smb_fname_src->st.st_ex_size = 0;
6561 /* Do the actual copy. */
6562 if (smb_fname_src->st.st_ex_size) {
6563 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6566 close_file(NULL, fsp1, NORMAL_CLOSE);
6568 /* Ensure the modtime is set correctly on the destination file. */
6569 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6572 * As we are opening fsp1 read-only we only expect
6573 * an error on close on fsp2 if we are out of space.
6574 * Thus we don't look at the error return from the
6577 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6579 if (!NT_STATUS_IS_OK(status)) {
6583 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6584 status = NT_STATUS_DISK_FULL;
6588 status = NT_STATUS_OK;
6591 TALLOC_FREE(smb_fname_dst_tmp);
6595 /****************************************************************************
6596 Reply to a file copy.
6597 ****************************************************************************/
6599 void reply_copy(struct smb_request *req)
6601 connection_struct *conn = req->conn;
6602 struct smb_filename *smb_fname_src = NULL;
6603 struct smb_filename *smb_fname_dst = NULL;
6604 char *fname_src = NULL;
6605 char *fname_dst = NULL;
6606 char *fname_src_mask = NULL;
6607 char *fname_src_dir = NULL;
6610 int error = ERRnoaccess;
6614 bool target_is_directory=False;
6615 bool source_has_wild = False;
6616 bool dest_has_wild = False;
6618 TALLOC_CTX *ctx = talloc_tos();
6620 START_PROFILE(SMBcopy);
6623 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6627 tid2 = SVAL(req->vwv+0, 0);
6628 ofun = SVAL(req->vwv+1, 0);
6629 flags = SVAL(req->vwv+2, 0);
6631 p = (const char *)req->buf;
6632 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6633 &status, &source_has_wild);
6634 if (!NT_STATUS_IS_OK(status)) {
6635 reply_nterror(req, status);
6638 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6639 &status, &dest_has_wild);
6640 if (!NT_STATUS_IS_OK(status)) {
6641 reply_nterror(req, status);
6645 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6647 if (tid2 != conn->cnum) {
6648 /* can't currently handle inter share copies XXXX */
6649 DEBUG(3,("Rejecting inter-share copy\n"));
6650 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6654 status = filename_convert(ctx, conn,
6655 req->flags2 & FLAGS2_DFS_PATHNAMES,
6657 UCF_COND_ALLOW_WCARD_LCOMP,
6660 if (!NT_STATUS_IS_OK(status)) {
6661 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6662 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6663 ERRSRV, ERRbadpath);
6666 reply_nterror(req, status);
6670 status = filename_convert(ctx, conn,
6671 req->flags2 & FLAGS2_DFS_PATHNAMES,
6673 UCF_COND_ALLOW_WCARD_LCOMP,
6676 if (!NT_STATUS_IS_OK(status)) {
6677 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6678 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6679 ERRSRV, ERRbadpath);
6682 reply_nterror(req, status);
6686 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6688 if ((flags&1) && target_is_directory) {
6689 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6693 if ((flags&2) && !target_is_directory) {
6694 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6698 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6699 /* wants a tree copy! XXXX */
6700 DEBUG(3,("Rejecting tree copy\n"));
6701 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6705 /* Split up the directory from the filename/mask. */
6706 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6707 &fname_src_dir, &fname_src_mask);
6708 if (!NT_STATUS_IS_OK(status)) {
6709 reply_nterror(req, NT_STATUS_NO_MEMORY);
6714 * We should only check the mangled cache
6715 * here if unix_convert failed. This means
6716 * that the path in 'mask' doesn't exist
6717 * on the file system and so we need to look
6718 * for a possible mangle. This patch from
6719 * Tine Smukavec <valentin.smukavec@hermes.si>.
6721 if (!VALID_STAT(smb_fname_src->st) &&
6722 mangle_is_mangled(fname_src_mask, conn->params)) {
6723 char *new_mask = NULL;
6724 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6725 &new_mask, conn->params);
6727 /* Use demangled name if one was successfully found. */
6729 TALLOC_FREE(fname_src_mask);
6730 fname_src_mask = new_mask;
6734 if (!source_has_wild) {
6737 * Only one file needs to be copied. Append the mask back onto
6740 TALLOC_FREE(smb_fname_src->base_name);
6741 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6745 if (!smb_fname_src->base_name) {
6746 reply_nterror(req, NT_STATUS_NO_MEMORY);
6750 if (dest_has_wild) {
6751 char *fname_dst_mod = NULL;
6752 if (!resolve_wildcards(smb_fname_dst,
6753 smb_fname_src->base_name,
6754 smb_fname_dst->base_name,
6756 reply_nterror(req, NT_STATUS_NO_MEMORY);
6759 TALLOC_FREE(smb_fname_dst->base_name);
6760 smb_fname_dst->base_name = fname_dst_mod;
6763 status = check_name(conn, smb_fname_src->base_name);
6764 if (!NT_STATUS_IS_OK(status)) {
6765 reply_nterror(req, status);
6769 status = check_name(conn, smb_fname_dst->base_name);
6770 if (!NT_STATUS_IS_OK(status)) {
6771 reply_nterror(req, status);
6775 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6776 ofun, count, target_is_directory);
6778 if(!NT_STATUS_IS_OK(status)) {
6779 reply_nterror(req, status);
6785 struct smb_Dir *dir_hnd = NULL;
6786 const char *dname = NULL;
6787 char *talloced = NULL;
6791 * There is a wildcard that requires us to actually read the
6792 * src dir and copy each file matching the mask to the dst.
6793 * Right now streams won't be copied, but this could
6794 * presumably be added with a nested loop for reach dir entry.
6796 SMB_ASSERT(!smb_fname_src->stream_name);
6797 SMB_ASSERT(!smb_fname_dst->stream_name);
6799 smb_fname_src->stream_name = NULL;
6800 smb_fname_dst->stream_name = NULL;
6802 if (strequal(fname_src_mask,"????????.???")) {
6803 TALLOC_FREE(fname_src_mask);
6804 fname_src_mask = talloc_strdup(ctx, "*");
6805 if (!fname_src_mask) {
6806 reply_nterror(req, NT_STATUS_NO_MEMORY);
6811 status = check_name(conn, fname_src_dir);
6812 if (!NT_STATUS_IS_OK(status)) {
6813 reply_nterror(req, status);
6817 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6818 if (dir_hnd == NULL) {
6819 status = map_nt_error_from_unix(errno);
6820 reply_nterror(req, status);
6826 /* Iterate over the src dir copying each entry to the dst. */
6827 while ((dname = ReadDirName(dir_hnd, &offset,
6828 &smb_fname_src->st, &talloced))) {
6829 char *destname = NULL;
6831 if (ISDOT(dname) || ISDOTDOT(dname)) {
6832 TALLOC_FREE(talloced);
6836 if (!is_visible_file(conn, fname_src_dir, dname,
6837 &smb_fname_src->st, false)) {
6838 TALLOC_FREE(talloced);
6842 if(!mask_match(dname, fname_src_mask,
6843 conn->case_sensitive)) {
6844 TALLOC_FREE(talloced);
6848 error = ERRnoaccess;
6850 /* Get the src smb_fname struct setup. */
6851 TALLOC_FREE(smb_fname_src->base_name);
6852 smb_fname_src->base_name =
6853 talloc_asprintf(smb_fname_src, "%s/%s",
6854 fname_src_dir, dname);
6856 if (!smb_fname_src->base_name) {
6857 TALLOC_FREE(dir_hnd);
6858 TALLOC_FREE(talloced);
6859 reply_nterror(req, NT_STATUS_NO_MEMORY);
6863 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6864 smb_fname_dst->base_name,
6866 TALLOC_FREE(talloced);
6870 TALLOC_FREE(dir_hnd);
6871 TALLOC_FREE(talloced);
6872 reply_nterror(req, NT_STATUS_NO_MEMORY);
6876 TALLOC_FREE(smb_fname_dst->base_name);
6877 smb_fname_dst->base_name = destname;
6879 status = check_name(conn, smb_fname_src->base_name);
6880 if (!NT_STATUS_IS_OK(status)) {
6881 TALLOC_FREE(dir_hnd);
6882 TALLOC_FREE(talloced);
6883 reply_nterror(req, status);
6887 status = check_name(conn, smb_fname_dst->base_name);
6888 if (!NT_STATUS_IS_OK(status)) {
6889 TALLOC_FREE(dir_hnd);
6890 TALLOC_FREE(talloced);
6891 reply_nterror(req, status);
6895 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
6896 smb_fname_src->base_name,
6897 smb_fname_dst->base_name));
6899 status = copy_file(ctx, conn, smb_fname_src,
6900 smb_fname_dst, ofun, count,
6901 target_is_directory);
6902 if (NT_STATUS_IS_OK(status)) {
6906 TALLOC_FREE(talloced);
6908 TALLOC_FREE(dir_hnd);
6912 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
6916 reply_outbuf(req, 1, 0);
6917 SSVAL(req->outbuf,smb_vwv0,count);
6919 TALLOC_FREE(smb_fname_src);
6920 TALLOC_FREE(smb_fname_dst);
6921 TALLOC_FREE(fname_src);
6922 TALLOC_FREE(fname_dst);
6923 TALLOC_FREE(fname_src_mask);
6924 TALLOC_FREE(fname_src_dir);
6926 END_PROFILE(SMBcopy);
6931 #define DBGC_CLASS DBGC_LOCKING
6933 /****************************************************************************
6934 Get a lock pid, dealing with large count requests.
6935 ****************************************************************************/
6937 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
6938 bool large_file_format)
6940 if(!large_file_format)
6941 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
6943 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6946 /****************************************************************************
6947 Get a lock count, dealing with large count requests.
6948 ****************************************************************************/
6950 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6951 bool large_file_format)
6955 if(!large_file_format) {
6956 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6959 #if defined(HAVE_LONGLONG)
6960 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6961 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6962 #else /* HAVE_LONGLONG */
6965 * NT4.x seems to be broken in that it sends large file (64 bit)
6966 * lockingX calls even if the CAP_LARGE_FILES was *not*
6967 * negotiated. For boxes without large unsigned ints truncate the
6968 * lock count by dropping the top 32 bits.
6971 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6972 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6973 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6974 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6975 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6978 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6979 #endif /* HAVE_LONGLONG */
6985 #if !defined(HAVE_LONGLONG)
6986 /****************************************************************************
6987 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6988 ****************************************************************************/
6990 static uint32 map_lock_offset(uint32 high, uint32 low)
6994 uint32 highcopy = high;
6997 * Try and find out how many significant bits there are in high.
7000 for(i = 0; highcopy; i++)
7004 * We use 31 bits not 32 here as POSIX
7005 * lock offsets may not be negative.
7008 mask = (~0) << (31 - i);
7011 return 0; /* Fail. */
7017 #endif /* !defined(HAVE_LONGLONG) */
7019 /****************************************************************************
7020 Get a lock offset, dealing with large offset requests.
7021 ****************************************************************************/
7023 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7024 bool large_file_format, bool *err)
7026 uint64_t offset = 0;
7030 if(!large_file_format) {
7031 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7034 #if defined(HAVE_LONGLONG)
7035 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7036 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7037 #else /* HAVE_LONGLONG */
7040 * NT4.x seems to be broken in that it sends large file (64 bit)
7041 * lockingX calls even if the CAP_LARGE_FILES was *not*
7042 * negotiated. For boxes without large unsigned ints mangle the
7043 * lock offset by mapping the top 32 bits onto the lower 32.
7046 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7047 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7048 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7051 if((new_low = map_lock_offset(high, low)) == 0) {
7053 return (uint64_t)-1;
7056 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7057 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7058 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7059 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7062 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7063 #endif /* HAVE_LONGLONG */
7069 NTSTATUS smbd_do_locking(struct smb_request *req,
7073 uint16_t num_ulocks,
7074 struct smbd_lock_element *ulocks,
7076 struct smbd_lock_element *locks,
7079 connection_struct *conn = req->conn;
7081 NTSTATUS status = NT_STATUS_OK;
7085 /* Data now points at the beginning of the list
7086 of smb_unlkrng structs */
7087 for(i = 0; i < (int)num_ulocks; i++) {
7088 struct smbd_lock_element *e = &ulocks[i];
7090 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7091 "pid %u, file %s\n",
7094 (unsigned int)e->smblctx,
7097 if (e->brltype != UNLOCK_LOCK) {
7098 /* this can only happen with SMB2 */
7099 return NT_STATUS_INVALID_PARAMETER;
7102 status = do_unlock(smbd_messaging_context(),
7109 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7110 nt_errstr(status)));
7112 if (!NT_STATUS_IS_OK(status)) {
7117 /* Setup the timeout in seconds. */
7119 if (!lp_blocking_locks(SNUM(conn))) {
7123 /* Data now points at the beginning of the list
7124 of smb_lkrng structs */
7126 for(i = 0; i < (int)num_locks; i++) {
7127 struct smbd_lock_element *e = &locks[i];
7129 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7130 "%llu, file %s timeout = %d\n",
7133 (unsigned long long)e->smblctx,
7137 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7138 struct blocking_lock_record *blr = NULL;
7140 if (num_locks > 1) {
7142 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7143 * if the lock vector contains one entry. When given mutliple cancel
7144 * requests in a single PDU we expect the server to return an
7145 * error. Windows servers seem to accept the request but only
7146 * cancel the first lock.
7147 * JRA - Do what Windows does (tm) :-).
7151 /* MS-CIFS (2.2.4.32.1) behavior. */
7152 return NT_STATUS_DOS(ERRDOS,
7153 ERRcancelviolation);
7155 /* Windows behavior. */
7157 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7158 "cancel request\n"));
7164 if (lp_blocking_locks(SNUM(conn))) {
7166 /* Schedule a message to ourselves to
7167 remove the blocking lock record and
7168 return the right error. */
7170 blr = blocking_lock_cancel_smb1(fsp,
7176 NT_STATUS_FILE_LOCK_CONFLICT);
7178 return NT_STATUS_DOS(
7180 ERRcancelviolation);
7183 /* Remove a matching pending lock. */
7184 status = do_lock_cancel(fsp,
7191 bool blocking_lock = timeout ? true : false;
7192 bool defer_lock = false;
7193 struct byte_range_lock *br_lck;
7194 uint64_t block_smblctx;
7196 br_lck = do_lock(smbd_messaging_context(),
7208 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7209 /* Windows internal resolution for blocking locks seems
7210 to be about 200ms... Don't wait for less than that. JRA. */
7211 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7212 timeout = lp_lock_spin_time();
7217 /* If a lock sent with timeout of zero would fail, and
7218 * this lock has been requested multiple times,
7219 * according to brl_lock_failed() we convert this
7220 * request to a blocking lock with a timeout of between
7221 * 150 - 300 milliseconds.
7223 * If lp_lock_spin_time() has been set to 0, we skip
7224 * this blocking retry and fail immediately.
7226 * Replacement for do_lock_spin(). JRA. */
7228 if (!smbd_server_conn->using_smb2 &&
7229 br_lck && lp_blocking_locks(SNUM(conn)) &&
7230 lp_lock_spin_time() && !blocking_lock &&
7231 NT_STATUS_EQUAL((status),
7232 NT_STATUS_FILE_LOCK_CONFLICT))
7235 timeout = lp_lock_spin_time();
7238 if (br_lck && defer_lock) {
7240 * A blocking lock was requested. Package up
7241 * this smb into a queued request and push it
7242 * onto the blocking lock queue.
7244 if(push_blocking_lock_request(br_lck,
7255 TALLOC_FREE(br_lck);
7257 return NT_STATUS_OK;
7261 TALLOC_FREE(br_lck);
7264 if (!NT_STATUS_IS_OK(status)) {
7269 /* If any of the above locks failed, then we must unlock
7270 all of the previous locks (X/Open spec). */
7272 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7274 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7275 i = -1; /* we want to skip the for loop */
7279 * Ensure we don't do a remove on the lock that just failed,
7280 * as under POSIX rules, if we have a lock already there, we
7281 * will delete it (and we shouldn't) .....
7283 for(i--; i >= 0; i--) {
7284 struct smbd_lock_element *e = &locks[i];
7286 do_unlock(smbd_messaging_context(),
7296 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7297 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7299 return NT_STATUS_OK;
7302 /****************************************************************************
7303 Reply to a lockingX request.
7304 ****************************************************************************/
7306 void reply_lockingX(struct smb_request *req)
7308 connection_struct *conn = req->conn;
7310 unsigned char locktype;
7311 unsigned char oplocklevel;
7316 const uint8_t *data;
7317 bool large_file_format;
7319 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7320 struct smbd_lock_element *ulocks;
7321 struct smbd_lock_element *locks;
7324 START_PROFILE(SMBlockingX);
7327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7328 END_PROFILE(SMBlockingX);
7332 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7333 locktype = CVAL(req->vwv+3, 0);
7334 oplocklevel = CVAL(req->vwv+3, 1);
7335 num_ulocks = SVAL(req->vwv+6, 0);
7336 num_locks = SVAL(req->vwv+7, 0);
7337 lock_timeout = IVAL(req->vwv+4, 0);
7338 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7340 if (!check_fsp(conn, req, fsp)) {
7341 END_PROFILE(SMBlockingX);
7347 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7348 /* we don't support these - and CANCEL_LOCK makes w2k
7349 and XP reboot so I don't really want to be
7350 compatible! (tridge) */
7351 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7352 END_PROFILE(SMBlockingX);
7356 /* Check if this is an oplock break on a file
7357 we have granted an oplock on.
7359 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7360 /* Client can insist on breaking to none. */
7361 bool break_to_none = (oplocklevel == 0);
7364 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7365 "for fnum = %d\n", (unsigned int)oplocklevel,
7369 * Make sure we have granted an exclusive or batch oplock on
7373 if (fsp->oplock_type == 0) {
7375 /* The Samba4 nbench simulator doesn't understand
7376 the difference between break to level2 and break
7377 to none from level2 - it sends oplock break
7378 replies in both cases. Don't keep logging an error
7379 message here - just ignore it. JRA. */
7381 DEBUG(5,("reply_lockingX: Error : oplock break from "
7382 "client for fnum = %d (oplock=%d) and no "
7383 "oplock granted on this file (%s).\n",
7384 fsp->fnum, fsp->oplock_type,
7387 /* if this is a pure oplock break request then don't
7389 if (num_locks == 0 && num_ulocks == 0) {
7390 END_PROFILE(SMBlockingX);
7393 END_PROFILE(SMBlockingX);
7394 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7399 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7401 result = remove_oplock(fsp);
7403 result = downgrade_oplock(fsp);
7407 DEBUG(0, ("reply_lockingX: error in removing "
7408 "oplock on file %s\n", fsp_str_dbg(fsp)));
7409 /* Hmmm. Is this panic justified? */
7410 smb_panic("internal tdb error");
7413 reply_to_oplock_break_requests(fsp);
7415 /* if this is a pure oplock break request then don't send a
7417 if (num_locks == 0 && num_ulocks == 0) {
7418 /* Sanity check - ensure a pure oplock break is not a
7420 if(CVAL(req->vwv+0, 0) != 0xff)
7421 DEBUG(0,("reply_lockingX: Error : pure oplock "
7422 "break is a chained %d request !\n",
7423 (unsigned int)CVAL(req->vwv+0, 0)));
7424 END_PROFILE(SMBlockingX);
7430 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7431 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7432 END_PROFILE(SMBlockingX);
7436 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7437 if (ulocks == NULL) {
7438 reply_nterror(req, NT_STATUS_NO_MEMORY);
7439 END_PROFILE(SMBlockingX);
7443 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7444 if (locks == NULL) {
7445 reply_nterror(req, NT_STATUS_NO_MEMORY);
7446 END_PROFILE(SMBlockingX);
7450 /* Data now points at the beginning of the list
7451 of smb_unlkrng structs */
7452 for(i = 0; i < (int)num_ulocks; i++) {
7453 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7454 ulocks[i].count = get_lock_count(data, i, large_file_format);
7455 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7456 ulocks[i].brltype = UNLOCK_LOCK;
7459 * There is no error code marked "stupid client bug".... :-).
7462 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7463 END_PROFILE(SMBlockingX);
7468 /* Now do any requested locks */
7469 data += ((large_file_format ? 20 : 10)*num_ulocks);
7471 /* Data now points at the beginning of the list
7472 of smb_lkrng structs */
7474 for(i = 0; i < (int)num_locks; i++) {
7475 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7476 locks[i].count = get_lock_count(data, i, large_file_format);
7477 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7479 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7480 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7481 locks[i].brltype = PENDING_READ_LOCK;
7483 locks[i].brltype = READ_LOCK;
7486 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7487 locks[i].brltype = PENDING_WRITE_LOCK;
7489 locks[i].brltype = WRITE_LOCK;
7494 * There is no error code marked "stupid client bug".... :-).
7497 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7498 END_PROFILE(SMBlockingX);
7503 status = smbd_do_locking(req, fsp,
7504 locktype, lock_timeout,
7508 if (!NT_STATUS_IS_OK(status)) {
7509 END_PROFILE(SMBlockingX);
7510 reply_nterror(req, status);
7514 END_PROFILE(SMBlockingX);
7518 reply_outbuf(req, 2, 0);
7520 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7521 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7523 END_PROFILE(SMBlockingX);
7528 #define DBGC_CLASS DBGC_ALL
7530 /****************************************************************************
7531 Reply to a SMBreadbmpx (read block multiplex) request.
7532 Always reply with an error, if someone has a platform really needs this,
7533 please contact vl@samba.org
7534 ****************************************************************************/
7536 void reply_readbmpx(struct smb_request *req)
7538 START_PROFILE(SMBreadBmpx);
7539 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7540 END_PROFILE(SMBreadBmpx);
7544 /****************************************************************************
7545 Reply to a SMBreadbs (read block multiplex secondary) request.
7546 Always reply with an error, if someone has a platform really needs this,
7547 please contact vl@samba.org
7548 ****************************************************************************/
7550 void reply_readbs(struct smb_request *req)
7552 START_PROFILE(SMBreadBs);
7553 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7554 END_PROFILE(SMBreadBs);
7558 /****************************************************************************
7559 Reply to a SMBsetattrE.
7560 ****************************************************************************/
7562 void reply_setattrE(struct smb_request *req)
7564 connection_struct *conn = req->conn;
7565 struct smb_file_time ft;
7569 START_PROFILE(SMBsetattrE);
7573 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7577 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7579 if(!fsp || (fsp->conn != conn)) {
7580 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7585 * Convert the DOS times into unix times.
7588 ft.atime = convert_time_t_to_timespec(
7589 srv_make_unix_date2(req->vwv+3));
7590 ft.mtime = convert_time_t_to_timespec(
7591 srv_make_unix_date2(req->vwv+5));
7592 ft.create_time = convert_time_t_to_timespec(
7593 srv_make_unix_date2(req->vwv+1));
7595 reply_outbuf(req, 0, 0);
7598 * Patch from Ray Frush <frush@engr.colostate.edu>
7599 * Sometimes times are sent as zero - ignore them.
7602 /* Ensure we have a valid stat struct for the source. */
7603 status = vfs_stat_fsp(fsp);
7604 if (!NT_STATUS_IS_OK(status)) {
7605 reply_nterror(req, status);
7609 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7610 if (!NT_STATUS_IS_OK(status)) {
7611 reply_nterror(req, status);
7615 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7618 (unsigned int)ft.atime.tv_sec,
7619 (unsigned int)ft.mtime.tv_sec,
7620 (unsigned int)ft.create_time.tv_sec
7623 END_PROFILE(SMBsetattrE);
7628 /* Back from the dead for OS/2..... JRA. */
7630 /****************************************************************************
7631 Reply to a SMBwritebmpx (write block multiplex primary) request.
7632 Always reply with an error, if someone has a platform really needs this,
7633 please contact vl@samba.org
7634 ****************************************************************************/
7636 void reply_writebmpx(struct smb_request *req)
7638 START_PROFILE(SMBwriteBmpx);
7639 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7640 END_PROFILE(SMBwriteBmpx);
7644 /****************************************************************************
7645 Reply to a SMBwritebs (write block multiplex secondary) request.
7646 Always reply with an error, if someone has a platform really needs this,
7647 please contact vl@samba.org
7648 ****************************************************************************/
7650 void reply_writebs(struct smb_request *req)
7652 START_PROFILE(SMBwriteBs);
7653 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7654 END_PROFILE(SMBwriteBs);
7658 /****************************************************************************
7659 Reply to a SMBgetattrE.
7660 ****************************************************************************/
7662 void reply_getattrE(struct smb_request *req)
7664 connection_struct *conn = req->conn;
7667 struct timespec create_ts;
7669 START_PROFILE(SMBgetattrE);
7672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7673 END_PROFILE(SMBgetattrE);
7677 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7679 if(!fsp || (fsp->conn != conn)) {
7680 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7681 END_PROFILE(SMBgetattrE);
7685 /* Do an fstat on this file */
7687 reply_nterror(req, map_nt_error_from_unix(errno));
7688 END_PROFILE(SMBgetattrE);
7692 mode = dos_mode(conn, fsp->fsp_name);
7695 * Convert the times into dos times. Set create
7696 * date to be last modify date as UNIX doesn't save
7700 reply_outbuf(req, 11, 0);
7702 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7703 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7704 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7705 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7706 /* Should we check pending modtime here ? JRA */
7707 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7708 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7711 SIVAL(req->outbuf, smb_vwv6, 0);
7712 SIVAL(req->outbuf, smb_vwv8, 0);
7714 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7715 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7716 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7718 SSVAL(req->outbuf,smb_vwv10, mode);
7720 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7722 END_PROFILE(SMBgetattrE);