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
29 #include "smbd/globals.h"
30 #include "../librpc/gen_ndr/cli_spoolss.h"
31 #include "rpc_client/cli_spoolss.h"
32 #include "rpc_client/init_spoolss.h"
34 /****************************************************************************
35 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
36 path or anything including wildcards.
37 We're assuming here that '/' is not the second byte in any multibyte char
38 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
40 ****************************************************************************/
42 /* Custom version for processing POSIX paths. */
43 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
45 static NTSTATUS check_path_syntax_internal(char *path,
47 bool *p_last_component_contains_wcard)
51 NTSTATUS ret = NT_STATUS_OK;
52 bool start_of_name_component = True;
53 bool stream_started = false;
55 *p_last_component_contains_wcard = False;
62 return NT_STATUS_OBJECT_NAME_INVALID;
65 return NT_STATUS_OBJECT_NAME_INVALID;
67 if (strchr_m(&s[1], ':')) {
68 return NT_STATUS_OBJECT_NAME_INVALID;
74 if ((*s == ':') && !posix_path && !stream_started) {
75 if (*p_last_component_contains_wcard) {
76 return NT_STATUS_OBJECT_NAME_INVALID;
78 /* Stream names allow more characters than file names.
79 We're overloading posix_path here to allow a wider
80 range of characters. If stream_started is true this
81 is still a Windows path even if posix_path is true.
84 stream_started = true;
85 start_of_name_component = false;
89 return NT_STATUS_OBJECT_NAME_INVALID;
93 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
95 * Safe to assume is not the second part of a mb char
96 * as this is handled below.
98 /* Eat multiple '/' or '\\' */
99 while (IS_PATH_SEP(*s,posix_path)) {
102 if ((d != path) && (*s != '\0')) {
103 /* We only care about non-leading or trailing '/' or '\\' */
107 start_of_name_component = True;
109 *p_last_component_contains_wcard = False;
113 if (start_of_name_component) {
114 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
115 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
118 * No mb char starts with '.' so we're safe checking the directory separator here.
121 /* If we just added a '/' - delete it */
122 if ((d > path) && (*(d-1) == '/')) {
127 /* Are we at the start ? Can't go back further if so. */
129 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
132 /* Go back one level... */
133 /* We know this is safe as '/' cannot be part of a mb sequence. */
134 /* NOTE - if this assumption is invalid we are not in good shape... */
135 /* Decrement d first as d points to the *next* char to write into. */
136 for (d--; d > path; d--) {
140 s += 2; /* Else go past the .. */
141 /* We're still at the start of a name component, just the previous one. */
144 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
156 if (*s <= 0x1f || *s == '|') {
157 return NT_STATUS_OBJECT_NAME_INVALID;
165 *p_last_component_contains_wcard = True;
174 /* Get the size of the next MB character. */
175 next_codepoint(s,&siz);
193 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
195 return NT_STATUS_INVALID_PARAMETER;
198 start_of_name_component = False;
206 /****************************************************************************
207 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
208 No wildcards allowed.
209 ****************************************************************************/
211 NTSTATUS check_path_syntax(char *path)
214 return check_path_syntax_internal(path, False, &ignore);
217 /****************************************************************************
218 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
219 Wildcards allowed - p_contains_wcard returns true if the last component contained
221 ****************************************************************************/
223 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
225 return check_path_syntax_internal(path, False, p_contains_wcard);
228 /****************************************************************************
229 Check the path for a POSIX client.
230 We're assuming here that '/' is not the second byte in any multibyte char
231 set (a safe assumption).
232 ****************************************************************************/
234 NTSTATUS check_path_syntax_posix(char *path)
237 return check_path_syntax_internal(path, True, &ignore);
240 /****************************************************************************
241 Pull a string and check the path allowing a wilcard - provide for error return.
242 ****************************************************************************/
244 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
245 const char *base_ptr,
252 bool *contains_wcard)
258 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
262 *err = NT_STATUS_INVALID_PARAMETER;
266 *contains_wcard = False;
268 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
270 * For a DFS path the function parse_dfs_path()
271 * will do the path processing, just make a copy.
277 if (lp_posix_pathnames()) {
278 *err = check_path_syntax_posix(*pp_dest);
280 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
286 /****************************************************************************
287 Pull a string and check the path - provide for error return.
288 ****************************************************************************/
290 size_t srvstr_get_path(TALLOC_CTX *ctx,
291 const char *base_ptr,
300 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
301 src_len, flags, err, &ignore);
304 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
305 char **pp_dest, const char *src, int flags,
306 NTSTATUS *err, bool *contains_wcard)
308 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
309 pp_dest, src, smbreq_bufrem(req, src),
310 flags, err, contains_wcard);
313 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
314 char **pp_dest, const char *src, int flags,
318 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
319 flags, err, &ignore);
322 /****************************************************************************
323 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
324 ****************************************************************************/
326 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
329 if ((fsp == NULL) || (conn == NULL)) {
330 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
333 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
334 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
340 /****************************************************************************
341 Check if we have a correct fsp pointing to a file.
342 ****************************************************************************/
344 bool check_fsp(connection_struct *conn, struct smb_request *req,
347 if (!check_fsp_open(conn, req, fsp)) {
350 if (fsp->is_directory) {
351 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
354 if (fsp->fh->fd == -1) {
355 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
358 fsp->num_smb_operations++;
362 /****************************************************************************
363 Check if we have a correct fsp pointing to a quota fake file. Replacement for
364 the CHECK_NTQUOTA_HANDLE_OK macro.
365 ****************************************************************************/
367 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
370 if (!check_fsp_open(conn, req, fsp)) {
374 if (fsp->is_directory) {
378 if (fsp->fake_file_handle == NULL) {
382 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
386 if (fsp->fake_file_handle->private_data == NULL) {
393 static bool netbios_session_retarget(const char *name, int name_type)
396 char *trim_name_type;
397 const char *retarget_parm;
400 int retarget_type = 0x20;
401 int retarget_port = 139;
402 struct sockaddr_storage retarget_addr;
403 struct sockaddr_in *in_addr;
407 if (get_socket_port(smbd_server_fd()) != 139) {
411 trim_name = talloc_strdup(talloc_tos(), name);
412 if (trim_name == NULL) {
415 trim_char(trim_name, ' ', ' ');
417 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
419 if (trim_name_type == NULL) {
423 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
424 trim_name_type, NULL);
425 if (retarget_parm == NULL) {
426 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
429 if (retarget_parm == NULL) {
433 retarget = talloc_strdup(trim_name, retarget_parm);
434 if (retarget == NULL) {
438 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
440 p = strchr(retarget, ':');
443 retarget_port = atoi(p);
446 p = strchr_m(retarget, '#');
449 sscanf(p, "%x", &retarget_type);
452 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
454 DEBUG(10, ("could not resolve %s\n", retarget));
458 if (retarget_addr.ss_family != AF_INET) {
459 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
463 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
465 _smb_setlen(outbuf, 6);
466 SCVAL(outbuf, 0, 0x84);
467 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
468 *(uint16_t *)(outbuf+8) = htons(retarget_port);
470 if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
472 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
478 TALLOC_FREE(trim_name);
482 /****************************************************************************
483 Reply to a (netbios-level) special message.
484 ****************************************************************************/
486 void reply_special(struct smbd_server_connection *sconn, char *inbuf)
488 int msg_type = CVAL(inbuf,0);
489 int msg_flags = CVAL(inbuf,1);
491 char name_type1, name_type2;
494 * We only really use 4 bytes of the outbuf, but for the smb_setlen
495 * calculation & friends (srv_send_smb uses that) we need the full smb
498 char outbuf[smb_size];
502 memset(outbuf, '\0', sizeof(outbuf));
504 smb_setlen(outbuf,0);
507 case 0x81: /* session request */
509 if (sconn->nbt.got_session) {
510 exit_server_cleanly("multiple session request not permitted");
513 SCVAL(outbuf,0,0x82);
515 if (name_len(inbuf+4) > 50 ||
516 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
517 DEBUG(0,("Invalid name length in session request\n"));
520 name_type1 = name_extract(inbuf,4,name1);
521 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
522 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
523 name1, name_type1, name2, name_type2));
525 if (netbios_session_retarget(name1, name_type1)) {
526 exit_server_cleanly("retargeted client");
529 set_local_machine_name(name1, True);
530 set_remote_machine_name(name2, True);
532 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
533 get_local_machine_name(), get_remote_machine_name(),
536 if (name_type2 == 'R') {
537 /* We are being asked for a pathworks session ---
539 SCVAL(outbuf, 0,0x83);
543 /* only add the client's machine name to the list
544 of possibly valid usernames if we are operating
545 in share mode security */
546 if (lp_security() == SEC_SHARE) {
547 add_session_user(sconn, get_remote_machine_name());
550 reload_services(sconn->msg_ctx, True);
553 sconn->nbt.got_session = true;
556 case 0x89: /* session keepalive request
557 (some old clients produce this?) */
558 SCVAL(outbuf,0,SMBkeepalive);
562 case 0x82: /* positive session response */
563 case 0x83: /* negative session response */
564 case 0x84: /* retarget session response */
565 DEBUG(0,("Unexpected session response\n"));
568 case SMBkeepalive: /* session keepalive */
573 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
574 msg_type, msg_flags));
576 srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
580 /****************************************************************************
582 conn POINTER CAN BE NULL HERE !
583 ****************************************************************************/
585 void reply_tcon(struct smb_request *req)
587 connection_struct *conn = req->conn;
589 char *service_buf = NULL;
590 char *password = NULL;
595 DATA_BLOB password_blob;
596 TALLOC_CTX *ctx = talloc_tos();
597 struct smbd_server_connection *sconn = req->sconn;
599 START_PROFILE(SMBtcon);
601 if (req->buflen < 4) {
602 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
603 END_PROFILE(SMBtcon);
607 p = (const char *)req->buf + 1;
608 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
610 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
612 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
615 if (service_buf == NULL || password == NULL || dev == NULL) {
616 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
617 END_PROFILE(SMBtcon);
620 p = strrchr_m(service_buf,'\\');
624 service = service_buf;
627 password_blob = data_blob(password, pwlen+1);
629 conn = make_connection(sconn,service,password_blob,dev,
630 req->vuid,&nt_status);
633 data_blob_clear_free(&password_blob);
636 reply_nterror(req, nt_status);
637 END_PROFILE(SMBtcon);
641 reply_outbuf(req, 2, 0);
642 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
643 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
644 SSVAL(req->outbuf,smb_tid,conn->cnum);
646 DEBUG(3,("tcon service=%s cnum=%d\n",
647 service, conn->cnum));
649 END_PROFILE(SMBtcon);
653 /****************************************************************************
654 Reply to a tcon and X.
655 conn POINTER CAN BE NULL HERE !
656 ****************************************************************************/
658 void reply_tcon_and_X(struct smb_request *req)
660 connection_struct *conn = req->conn;
661 const char *service = NULL;
663 TALLOC_CTX *ctx = talloc_tos();
664 /* what the cleint thinks the device is */
665 char *client_devicetype = NULL;
666 /* what the server tells the client the share represents */
667 const char *server_devicetype;
673 struct smbd_server_connection *sconn = req->sconn;
675 START_PROFILE(SMBtconX);
678 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
679 END_PROFILE(SMBtconX);
683 passlen = SVAL(req->vwv+3, 0);
684 tcon_flags = SVAL(req->vwv+2, 0);
686 /* we might have to close an old one */
687 if ((tcon_flags & 0x1) && conn) {
688 close_cnum(conn,req->vuid);
693 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
694 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
695 END_PROFILE(SMBtconX);
699 if (sconn->smb1.negprot.encrypted_passwords) {
700 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
701 if (lp_security() == SEC_SHARE) {
703 * Security = share always has a pad byte
704 * after the password.
706 p = (const char *)req->buf + passlen + 1;
708 p = (const char *)req->buf + passlen;
711 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
712 /* Ensure correct termination */
713 password.data[passlen]=0;
714 p = (const char *)req->buf + passlen + 1;
717 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
720 data_blob_clear_free(&password);
721 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
722 END_PROFILE(SMBtconX);
727 * the service name can be either: \\server\share
728 * or share directly like on the DELL PowerVault 705
731 q = strchr_m(path+2,'\\');
733 data_blob_clear_free(&password);
734 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
735 END_PROFILE(SMBtconX);
743 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
744 &client_devicetype, p,
745 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
747 if (client_devicetype == NULL) {
748 data_blob_clear_free(&password);
749 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
750 END_PROFILE(SMBtconX);
754 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
756 conn = make_connection(sconn, service, password, client_devicetype,
757 req->vuid, &nt_status);
760 data_blob_clear_free(&password);
763 reply_nterror(req, nt_status);
764 END_PROFILE(SMBtconX);
769 server_devicetype = "IPC";
770 else if ( IS_PRINT(conn) )
771 server_devicetype = "LPT1:";
773 server_devicetype = "A:";
775 if (get_Protocol() < PROTOCOL_NT1) {
776 reply_outbuf(req, 2, 0);
777 if (message_push_string(&req->outbuf, server_devicetype,
778 STR_TERMINATE|STR_ASCII) == -1) {
779 reply_nterror(req, NT_STATUS_NO_MEMORY);
780 END_PROFILE(SMBtconX);
784 /* NT sets the fstype of IPC$ to the null string */
785 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
787 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
788 /* Return permissions. */
792 reply_outbuf(req, 7, 0);
795 perm1 = FILE_ALL_ACCESS;
796 perm2 = FILE_ALL_ACCESS;
798 perm1 = CAN_WRITE(conn) ?
803 SIVAL(req->outbuf, smb_vwv3, perm1);
804 SIVAL(req->outbuf, smb_vwv5, perm2);
806 reply_outbuf(req, 3, 0);
809 if ((message_push_string(&req->outbuf, server_devicetype,
810 STR_TERMINATE|STR_ASCII) == -1)
811 || (message_push_string(&req->outbuf, fstype,
812 STR_TERMINATE) == -1)) {
813 reply_nterror(req, NT_STATUS_NO_MEMORY);
814 END_PROFILE(SMBtconX);
818 /* what does setting this bit do? It is set by NT4 and
819 may affect the ability to autorun mounted cdroms */
820 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
821 (lp_csc_policy(SNUM(conn)) << 2));
823 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
824 DEBUG(2,("Serving %s as a Dfs root\n",
825 lp_servicename(SNUM(conn)) ));
826 SSVAL(req->outbuf, smb_vwv2,
827 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
832 DEBUG(3,("tconX service=%s \n",
835 /* set the incoming and outgoing tid to the just created one */
836 SSVAL(req->inbuf,smb_tid,conn->cnum);
837 SSVAL(req->outbuf,smb_tid,conn->cnum);
839 END_PROFILE(SMBtconX);
841 req->tid = conn->cnum;
846 /****************************************************************************
847 Reply to an unknown type.
848 ****************************************************************************/
850 void reply_unknown_new(struct smb_request *req, uint8 type)
852 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
853 smb_fn_name(type), type, type));
854 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
858 /****************************************************************************
860 conn POINTER CAN BE NULL HERE !
861 ****************************************************************************/
863 void reply_ioctl(struct smb_request *req)
865 connection_struct *conn = req->conn;
872 START_PROFILE(SMBioctl);
875 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
876 END_PROFILE(SMBioctl);
880 device = SVAL(req->vwv+1, 0);
881 function = SVAL(req->vwv+2, 0);
882 ioctl_code = (device << 16) + function;
884 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
886 switch (ioctl_code) {
887 case IOCTL_QUERY_JOB_INFO:
891 reply_force_doserror(req, ERRSRV, ERRnosupport);
892 END_PROFILE(SMBioctl);
896 reply_outbuf(req, 8, replysize+1);
897 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
898 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
899 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
900 p = smb_buf(req->outbuf);
901 memset(p, '\0', replysize+1); /* valgrind-safe. */
902 p += 1; /* Allow for alignment */
904 switch (ioctl_code) {
905 case IOCTL_QUERY_JOB_INFO:
907 files_struct *fsp = file_fsp(
908 req, SVAL(req->vwv+0, 0));
910 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
911 END_PROFILE(SMBioctl);
915 if (fsp->print_file) {
916 SSVAL(p, 0, fsp->print_file->rap_jobid);
920 srvstr_push((char *)req->outbuf, req->flags2, p+2,
922 STR_TERMINATE|STR_ASCII);
924 srvstr_push((char *)req->outbuf, req->flags2,
925 p+18, lp_servicename(SNUM(conn)),
926 13, STR_TERMINATE|STR_ASCII);
934 END_PROFILE(SMBioctl);
938 /****************************************************************************
939 Strange checkpath NTSTATUS mapping.
940 ****************************************************************************/
942 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
944 /* Strange DOS error code semantics only for checkpath... */
945 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
946 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
947 /* We need to map to ERRbadpath */
948 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
954 /****************************************************************************
955 Reply to a checkpath.
956 ****************************************************************************/
958 void reply_checkpath(struct smb_request *req)
960 connection_struct *conn = req->conn;
961 struct smb_filename *smb_fname = NULL;
964 TALLOC_CTX *ctx = talloc_tos();
966 START_PROFILE(SMBcheckpath);
968 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
969 STR_TERMINATE, &status);
971 if (!NT_STATUS_IS_OK(status)) {
972 status = map_checkpath_error(req->flags2, status);
973 reply_nterror(req, status);
974 END_PROFILE(SMBcheckpath);
978 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
980 status = filename_convert(ctx,
982 req->flags2 & FLAGS2_DFS_PATHNAMES,
988 if (!NT_STATUS_IS_OK(status)) {
989 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
990 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
992 END_PROFILE(SMBcheckpath);
998 if (!VALID_STAT(smb_fname->st) &&
999 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1000 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1001 smb_fname_str_dbg(smb_fname), strerror(errno)));
1002 status = map_nt_error_from_unix(errno);
1006 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1007 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1008 ERRDOS, ERRbadpath);
1012 reply_outbuf(req, 0, 0);
1015 /* We special case this - as when a Windows machine
1016 is parsing a path is steps through the components
1017 one at a time - if a component fails it expects
1018 ERRbadpath, not ERRbadfile.
1020 status = map_checkpath_error(req->flags2, status);
1021 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1023 * Windows returns different error codes if
1024 * the parent directory is valid but not the
1025 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1026 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1027 * if the path is invalid.
1029 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1030 ERRDOS, ERRbadpath);
1034 reply_nterror(req, status);
1037 TALLOC_FREE(smb_fname);
1038 END_PROFILE(SMBcheckpath);
1042 /****************************************************************************
1044 ****************************************************************************/
1046 void reply_getatr(struct smb_request *req)
1048 connection_struct *conn = req->conn;
1049 struct smb_filename *smb_fname = NULL;
1056 TALLOC_CTX *ctx = talloc_tos();
1057 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1059 START_PROFILE(SMBgetatr);
1061 p = (const char *)req->buf + 1;
1062 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1063 if (!NT_STATUS_IS_OK(status)) {
1064 reply_nterror(req, status);
1068 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1069 under WfWg - weird! */
1070 if (*fname == '\0') {
1071 mode = aHIDDEN | aDIR;
1072 if (!CAN_WRITE(conn)) {
1078 status = filename_convert(ctx,
1080 req->flags2 & FLAGS2_DFS_PATHNAMES,
1085 if (!NT_STATUS_IS_OK(status)) {
1086 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1087 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1088 ERRSRV, ERRbadpath);
1091 reply_nterror(req, status);
1094 if (!VALID_STAT(smb_fname->st) &&
1095 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1096 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1097 smb_fname_str_dbg(smb_fname),
1099 reply_nterror(req, map_nt_error_from_unix(errno));
1103 mode = dos_mode(conn, smb_fname);
1104 size = smb_fname->st.st_ex_size;
1106 if (ask_sharemode) {
1107 struct timespec write_time_ts;
1108 struct file_id fileid;
1110 ZERO_STRUCT(write_time_ts);
1111 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1112 get_file_infos(fileid, NULL, &write_time_ts);
1113 if (!null_timespec(write_time_ts)) {
1114 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1118 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1124 reply_outbuf(req, 10, 0);
1126 SSVAL(req->outbuf,smb_vwv0,mode);
1127 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1128 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1130 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1132 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1134 if (get_Protocol() >= PROTOCOL_NT1) {
1135 SSVAL(req->outbuf, smb_flg2,
1136 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1139 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1140 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1143 TALLOC_FREE(smb_fname);
1145 END_PROFILE(SMBgetatr);
1149 /****************************************************************************
1151 ****************************************************************************/
1153 void reply_setatr(struct smb_request *req)
1155 struct smb_file_time ft;
1156 connection_struct *conn = req->conn;
1157 struct smb_filename *smb_fname = NULL;
1163 TALLOC_CTX *ctx = talloc_tos();
1165 START_PROFILE(SMBsetatr);
1170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1174 p = (const char *)req->buf + 1;
1175 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1176 if (!NT_STATUS_IS_OK(status)) {
1177 reply_nterror(req, status);
1181 status = filename_convert(ctx,
1183 req->flags2 & FLAGS2_DFS_PATHNAMES,
1188 if (!NT_STATUS_IS_OK(status)) {
1189 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1190 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1191 ERRSRV, ERRbadpath);
1194 reply_nterror(req, status);
1198 if (smb_fname->base_name[0] == '.' &&
1199 smb_fname->base_name[1] == '\0') {
1201 * Not sure here is the right place to catch this
1202 * condition. Might be moved to somewhere else later -- vl
1204 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1208 mode = SVAL(req->vwv+0, 0);
1209 mtime = srv_make_unix_date3(req->vwv+1);
1211 ft.mtime = convert_time_t_to_timespec(mtime);
1212 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1213 if (!NT_STATUS_IS_OK(status)) {
1214 reply_nterror(req, status);
1218 if (mode != FILE_ATTRIBUTE_NORMAL) {
1219 if (VALID_STAT_OF_DIR(smb_fname->st))
1224 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1226 reply_nterror(req, map_nt_error_from_unix(errno));
1231 reply_outbuf(req, 0, 0);
1233 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1236 TALLOC_FREE(smb_fname);
1237 END_PROFILE(SMBsetatr);
1241 /****************************************************************************
1243 ****************************************************************************/
1245 void reply_dskattr(struct smb_request *req)
1247 connection_struct *conn = req->conn;
1248 uint64_t dfree,dsize,bsize;
1249 START_PROFILE(SMBdskattr);
1251 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1252 reply_nterror(req, map_nt_error_from_unix(errno));
1253 END_PROFILE(SMBdskattr);
1257 reply_outbuf(req, 5, 0);
1259 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1260 double total_space, free_space;
1261 /* we need to scale this to a number that DOS6 can handle. We
1262 use floating point so we can handle large drives on systems
1263 that don't have 64 bit integers
1265 we end up displaying a maximum of 2G to DOS systems
1267 total_space = dsize * (double)bsize;
1268 free_space = dfree * (double)bsize;
1270 dsize = (uint64_t)((total_space+63*512) / (64*512));
1271 dfree = (uint64_t)((free_space+63*512) / (64*512));
1273 if (dsize > 0xFFFF) dsize = 0xFFFF;
1274 if (dfree > 0xFFFF) dfree = 0xFFFF;
1276 SSVAL(req->outbuf,smb_vwv0,dsize);
1277 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1278 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1279 SSVAL(req->outbuf,smb_vwv3,dfree);
1281 SSVAL(req->outbuf,smb_vwv0,dsize);
1282 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1283 SSVAL(req->outbuf,smb_vwv2,512);
1284 SSVAL(req->outbuf,smb_vwv3,dfree);
1287 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1289 END_PROFILE(SMBdskattr);
1294 * Utility function to split the filename from the directory.
1296 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1297 char **fname_dir_out,
1298 char **fname_mask_out)
1300 const char *p = NULL;
1301 char *fname_dir = NULL;
1302 char *fname_mask = NULL;
1304 p = strrchr_m(fname_in, '/');
1306 fname_dir = talloc_strdup(ctx, ".");
1307 fname_mask = talloc_strdup(ctx, fname_in);
1309 fname_dir = talloc_strndup(ctx, fname_in,
1310 PTR_DIFF(p, fname_in));
1311 fname_mask = talloc_strdup(ctx, p+1);
1314 if (!fname_dir || !fname_mask) {
1315 TALLOC_FREE(fname_dir);
1316 TALLOC_FREE(fname_mask);
1317 return NT_STATUS_NO_MEMORY;
1320 *fname_dir_out = fname_dir;
1321 *fname_mask_out = fname_mask;
1322 return NT_STATUS_OK;
1325 /****************************************************************************
1327 Can be called from SMBsearch, SMBffirst or SMBfunique.
1328 ****************************************************************************/
1330 void reply_search(struct smb_request *req)
1332 connection_struct *conn = req->conn;
1334 const char *mask = NULL;
1335 char *directory = NULL;
1336 struct smb_filename *smb_fname = NULL;
1340 struct timespec date;
1342 unsigned int numentries = 0;
1343 unsigned int maxentries = 0;
1344 bool finished = False;
1349 bool check_descend = False;
1350 bool expect_close = False;
1352 bool mask_contains_wcard = False;
1353 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1354 TALLOC_CTX *ctx = talloc_tos();
1355 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1356 struct dptr_struct *dirptr = NULL;
1357 struct smbd_server_connection *sconn = req->sconn;
1359 START_PROFILE(SMBsearch);
1362 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1366 if (lp_posix_pathnames()) {
1367 reply_unknown_new(req, req->cmd);
1371 /* If we were called as SMBffirst then we must expect close. */
1372 if(req->cmd == SMBffirst) {
1373 expect_close = True;
1376 reply_outbuf(req, 1, 3);
1377 maxentries = SVAL(req->vwv+0, 0);
1378 dirtype = SVAL(req->vwv+1, 0);
1379 p = (const char *)req->buf + 1;
1380 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1381 &nt_status, &mask_contains_wcard);
1382 if (!NT_STATUS_IS_OK(nt_status)) {
1383 reply_nterror(req, nt_status);
1388 status_len = SVAL(p, 0);
1391 /* dirtype &= ~aDIR; */
1393 if (status_len == 0) {
1394 nt_status = filename_convert(ctx, conn,
1395 req->flags2 & FLAGS2_DFS_PATHNAMES,
1397 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1398 &mask_contains_wcard,
1400 if (!NT_STATUS_IS_OK(nt_status)) {
1401 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1402 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1403 ERRSRV, ERRbadpath);
1406 reply_nterror(req, nt_status);
1410 directory = smb_fname->base_name;
1412 p = strrchr_m(directory,'/');
1413 if ((p != NULL) && (*directory != '/')) {
1415 directory = talloc_strndup(ctx, directory,
1416 PTR_DIFF(p, directory));
1419 directory = talloc_strdup(ctx,".");
1423 reply_nterror(req, NT_STATUS_NO_MEMORY);
1427 memset((char *)status,'\0',21);
1428 SCVAL(status,0,(dirtype & 0x1F));
1430 nt_status = dptr_create(conn,
1436 mask_contains_wcard,
1439 if (!NT_STATUS_IS_OK(nt_status)) {
1440 reply_nterror(req, nt_status);
1443 dptr_num = dptr_dnum(dirptr);
1446 const char *dirpath;
1448 memcpy(status,p,21);
1449 status_dirtype = CVAL(status,0) & 0x1F;
1450 if (status_dirtype != (dirtype & 0x1F)) {
1451 dirtype = status_dirtype;
1454 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1458 dirpath = dptr_path(sconn, dptr_num);
1459 directory = talloc_strdup(ctx, dirpath);
1461 reply_nterror(req, NT_STATUS_NO_MEMORY);
1465 mask = dptr_wcard(sconn, dptr_num);
1470 * For a 'continue' search we have no string. So
1471 * check from the initial saved string.
1473 mask_contains_wcard = ms_has_wild(mask);
1474 dirtype = dptr_attr(sconn, dptr_num);
1477 DEBUG(4,("dptr_num is %d\n",dptr_num));
1479 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1480 dptr_init_search_op(dirptr);
1482 if ((dirtype&0x1F) == aVOLID) {
1483 char buf[DIR_STRUCT_SIZE];
1484 memcpy(buf,status,21);
1485 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1486 0,aVOLID,0,!allow_long_path_components)) {
1487 reply_nterror(req, NT_STATUS_NO_MEMORY);
1490 dptr_fill(sconn, buf+12,dptr_num);
1491 if (dptr_zero(buf+12) && (status_len==0)) {
1496 if (message_push_blob(&req->outbuf,
1497 data_blob_const(buf, sizeof(buf)))
1499 reply_nterror(req, NT_STATUS_NO_MEMORY);
1507 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1510 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1511 directory,lp_dontdescend(SNUM(conn))));
1512 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1513 check_descend = True;
1516 for (i=numentries;(i<maxentries) && !finished;i++) {
1517 finished = !get_dir_entry(ctx,
1528 char buf[DIR_STRUCT_SIZE];
1529 memcpy(buf,status,21);
1530 if (!make_dir_struct(ctx,
1536 convert_timespec_to_time_t(date),
1537 !allow_long_path_components)) {
1538 reply_nterror(req, NT_STATUS_NO_MEMORY);
1541 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1544 if (message_push_blob(&req->outbuf,
1545 data_blob_const(buf, sizeof(buf)))
1547 reply_nterror(req, NT_STATUS_NO_MEMORY);
1557 /* If we were called as SMBffirst with smb_search_id == NULL
1558 and no entries were found then return error and close dirptr
1561 if (numentries == 0) {
1562 dptr_close(sconn, &dptr_num);
1563 } else if(expect_close && status_len == 0) {
1564 /* Close the dptr - we know it's gone */
1565 dptr_close(sconn, &dptr_num);
1568 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1569 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1570 dptr_close(sconn, &dptr_num);
1573 if ((numentries == 0) && !mask_contains_wcard) {
1574 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1578 SSVAL(req->outbuf,smb_vwv0,numentries);
1579 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1580 SCVAL(smb_buf(req->outbuf),0,5);
1581 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1583 /* The replies here are never long name. */
1584 SSVAL(req->outbuf, smb_flg2,
1585 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1586 if (!allow_long_path_components) {
1587 SSVAL(req->outbuf, smb_flg2,
1588 SVAL(req->outbuf, smb_flg2)
1589 & (~FLAGS2_LONG_PATH_COMPONENTS));
1592 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1593 SSVAL(req->outbuf, smb_flg2,
1594 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1596 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1597 smb_fn_name(req->cmd),
1604 TALLOC_FREE(directory);
1605 TALLOC_FREE(smb_fname);
1606 END_PROFILE(SMBsearch);
1610 /****************************************************************************
1611 Reply to a fclose (stop directory search).
1612 ****************************************************************************/
1614 void reply_fclose(struct smb_request *req)
1622 bool path_contains_wcard = False;
1623 TALLOC_CTX *ctx = talloc_tos();
1624 struct smbd_server_connection *sconn = req->sconn;
1626 START_PROFILE(SMBfclose);
1628 if (lp_posix_pathnames()) {
1629 reply_unknown_new(req, req->cmd);
1630 END_PROFILE(SMBfclose);
1634 p = (const char *)req->buf + 1;
1635 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1636 &err, &path_contains_wcard);
1637 if (!NT_STATUS_IS_OK(err)) {
1638 reply_nterror(req, err);
1639 END_PROFILE(SMBfclose);
1643 status_len = SVAL(p,0);
1646 if (status_len == 0) {
1647 reply_force_doserror(req, ERRSRV, ERRsrverror);
1648 END_PROFILE(SMBfclose);
1652 memcpy(status,p,21);
1654 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1655 /* Close the dptr - we know it's gone */
1656 dptr_close(sconn, &dptr_num);
1659 reply_outbuf(req, 1, 0);
1660 SSVAL(req->outbuf,smb_vwv0,0);
1662 DEBUG(3,("search close\n"));
1664 END_PROFILE(SMBfclose);
1668 /****************************************************************************
1670 ****************************************************************************/
1672 void reply_open(struct smb_request *req)
1674 connection_struct *conn = req->conn;
1675 struct smb_filename *smb_fname = NULL;
1687 uint32 create_disposition;
1688 uint32 create_options = 0;
1689 uint32_t private_flags = 0;
1691 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1692 TALLOC_CTX *ctx = talloc_tos();
1694 START_PROFILE(SMBopen);
1697 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1701 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1702 deny_mode = SVAL(req->vwv+0, 0);
1703 dos_attr = SVAL(req->vwv+1, 0);
1705 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1706 STR_TERMINATE, &status);
1707 if (!NT_STATUS_IS_OK(status)) {
1708 reply_nterror(req, status);
1712 status = filename_convert(ctx,
1714 req->flags2 & FLAGS2_DFS_PATHNAMES,
1719 if (!NT_STATUS_IS_OK(status)) {
1720 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1721 reply_botherror(req,
1722 NT_STATUS_PATH_NOT_COVERED,
1723 ERRSRV, ERRbadpath);
1726 reply_nterror(req, status);
1730 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1731 OPENX_FILE_EXISTS_OPEN, &access_mask,
1732 &share_mode, &create_disposition,
1733 &create_options, &private_flags)) {
1734 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1738 status = SMB_VFS_CREATE_FILE(
1741 0, /* root_dir_fid */
1742 smb_fname, /* fname */
1743 access_mask, /* access_mask */
1744 share_mode, /* share_access */
1745 create_disposition, /* create_disposition*/
1746 create_options, /* create_options */
1747 dos_attr, /* file_attributes */
1748 oplock_request, /* oplock_request */
1749 0, /* allocation_size */
1756 if (!NT_STATUS_IS_OK(status)) {
1757 if (open_was_deferred(req->mid)) {
1758 /* We have re-scheduled this call. */
1761 reply_openerror(req, status);
1765 size = smb_fname->st.st_ex_size;
1766 fattr = dos_mode(conn, smb_fname);
1768 /* Deal with other possible opens having a modified
1770 if (ask_sharemode) {
1771 struct timespec write_time_ts;
1773 ZERO_STRUCT(write_time_ts);
1774 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1775 if (!null_timespec(write_time_ts)) {
1776 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1780 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1783 DEBUG(3,("attempt to open a directory %s\n",
1785 close_file(req, fsp, ERROR_CLOSE);
1786 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1787 ERRDOS, ERRnoaccess);
1791 reply_outbuf(req, 7, 0);
1792 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1793 SSVAL(req->outbuf,smb_vwv1,fattr);
1794 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1795 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1797 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1799 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1800 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1802 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1803 SCVAL(req->outbuf,smb_flg,
1804 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1807 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1808 SCVAL(req->outbuf,smb_flg,
1809 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1812 TALLOC_FREE(smb_fname);
1813 END_PROFILE(SMBopen);
1817 /****************************************************************************
1818 Reply to an open and X.
1819 ****************************************************************************/
1821 void reply_open_and_X(struct smb_request *req)
1823 connection_struct *conn = req->conn;
1824 struct smb_filename *smb_fname = NULL;
1829 /* Breakout the oplock request bits so we can set the
1830 reply bits separately. */
1831 int ex_oplock_request;
1832 int core_oplock_request;
1835 int smb_sattr = SVAL(req->vwv+4, 0);
1836 uint32 smb_time = make_unix_date3(req->vwv+6);
1844 uint64_t allocation_size;
1845 ssize_t retval = -1;
1848 uint32 create_disposition;
1849 uint32 create_options = 0;
1850 uint32_t private_flags = 0;
1851 TALLOC_CTX *ctx = talloc_tos();
1853 START_PROFILE(SMBopenX);
1855 if (req->wct < 15) {
1856 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1860 open_flags = SVAL(req->vwv+2, 0);
1861 deny_mode = SVAL(req->vwv+3, 0);
1862 smb_attr = SVAL(req->vwv+5, 0);
1863 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1864 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1865 oplock_request = ex_oplock_request | core_oplock_request;
1866 smb_ofun = SVAL(req->vwv+8, 0);
1867 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1869 /* If it's an IPC, pass off the pipe handler. */
1871 if (lp_nt_pipe_support()) {
1872 reply_open_pipe_and_X(conn, req);
1874 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1879 /* XXXX we need to handle passed times, sattr and flags */
1880 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1881 STR_TERMINATE, &status);
1882 if (!NT_STATUS_IS_OK(status)) {
1883 reply_nterror(req, status);
1887 status = filename_convert(ctx,
1889 req->flags2 & FLAGS2_DFS_PATHNAMES,
1894 if (!NT_STATUS_IS_OK(status)) {
1895 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1896 reply_botherror(req,
1897 NT_STATUS_PATH_NOT_COVERED,
1898 ERRSRV, ERRbadpath);
1901 reply_nterror(req, status);
1905 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1906 &access_mask, &share_mode,
1907 &create_disposition,
1910 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1914 status = SMB_VFS_CREATE_FILE(
1917 0, /* root_dir_fid */
1918 smb_fname, /* fname */
1919 access_mask, /* access_mask */
1920 share_mode, /* share_access */
1921 create_disposition, /* create_disposition*/
1922 create_options, /* create_options */
1923 smb_attr, /* file_attributes */
1924 oplock_request, /* oplock_request */
1925 0, /* allocation_size */
1930 &smb_action); /* pinfo */
1932 if (!NT_STATUS_IS_OK(status)) {
1933 if (open_was_deferred(req->mid)) {
1934 /* We have re-scheduled this call. */
1937 reply_openerror(req, status);
1941 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1942 if the file is truncated or created. */
1943 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1944 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1945 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1946 close_file(req, fsp, ERROR_CLOSE);
1947 reply_nterror(req, NT_STATUS_DISK_FULL);
1950 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1952 close_file(req, fsp, ERROR_CLOSE);
1953 reply_nterror(req, NT_STATUS_DISK_FULL);
1956 smb_fname->st.st_ex_size =
1957 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1960 fattr = dos_mode(conn, smb_fname);
1961 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1963 close_file(req, fsp, ERROR_CLOSE);
1964 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1968 /* If the caller set the extended oplock request bit
1969 and we granted one (by whatever means) - set the
1970 correct bit for extended oplock reply.
1973 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1974 smb_action |= EXTENDED_OPLOCK_GRANTED;
1977 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1978 smb_action |= EXTENDED_OPLOCK_GRANTED;
1981 /* If the caller set the core oplock request bit
1982 and we granted one (by whatever means) - set the
1983 correct bit for core oplock reply.
1986 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1987 reply_outbuf(req, 19, 0);
1989 reply_outbuf(req, 15, 0);
1992 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1993 SCVAL(req->outbuf, smb_flg,
1994 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1997 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1998 SCVAL(req->outbuf, smb_flg,
1999 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2002 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2003 SSVAL(req->outbuf,smb_vwv3,fattr);
2004 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2005 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2007 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2009 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2010 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2011 SSVAL(req->outbuf,smb_vwv11,smb_action);
2013 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2014 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2019 TALLOC_FREE(smb_fname);
2020 END_PROFILE(SMBopenX);
2024 /****************************************************************************
2025 Reply to a SMBulogoffX.
2026 ****************************************************************************/
2028 void reply_ulogoffX(struct smb_request *req)
2030 struct smbd_server_connection *sconn = req->sconn;
2033 START_PROFILE(SMBulogoffX);
2035 vuser = get_valid_user_struct(sconn, req->vuid);
2038 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2042 /* in user level security we are supposed to close any files
2043 open by this user */
2044 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2045 file_close_user(req->vuid);
2048 invalidate_vuid(sconn, req->vuid);
2050 reply_outbuf(req, 2, 0);
2052 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2054 END_PROFILE(SMBulogoffX);
2055 req->vuid = UID_FIELD_INVALID;
2059 /****************************************************************************
2060 Reply to a mknew or a create.
2061 ****************************************************************************/
2063 void reply_mknew(struct smb_request *req)
2065 connection_struct *conn = req->conn;
2066 struct smb_filename *smb_fname = NULL;
2069 struct smb_file_time ft;
2071 int oplock_request = 0;
2073 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2074 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2075 uint32 create_disposition;
2076 uint32 create_options = 0;
2077 TALLOC_CTX *ctx = talloc_tos();
2079 START_PROFILE(SMBcreate);
2083 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2087 fattr = SVAL(req->vwv+0, 0);
2088 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2091 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2093 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2094 STR_TERMINATE, &status);
2095 if (!NT_STATUS_IS_OK(status)) {
2096 reply_nterror(req, status);
2100 status = filename_convert(ctx,
2102 req->flags2 & FLAGS2_DFS_PATHNAMES,
2107 if (!NT_STATUS_IS_OK(status)) {
2108 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2109 reply_botherror(req,
2110 NT_STATUS_PATH_NOT_COVERED,
2111 ERRSRV, ERRbadpath);
2114 reply_nterror(req, status);
2118 if (fattr & aVOLID) {
2119 DEBUG(0,("Attempt to create file (%s) with volid set - "
2120 "please report this\n",
2121 smb_fname_str_dbg(smb_fname)));
2124 if(req->cmd == SMBmknew) {
2125 /* We should fail if file exists. */
2126 create_disposition = FILE_CREATE;
2128 /* Create if file doesn't exist, truncate if it does. */
2129 create_disposition = FILE_OVERWRITE_IF;
2132 status = SMB_VFS_CREATE_FILE(
2135 0, /* root_dir_fid */
2136 smb_fname, /* fname */
2137 access_mask, /* access_mask */
2138 share_mode, /* share_access */
2139 create_disposition, /* create_disposition*/
2140 create_options, /* create_options */
2141 fattr, /* file_attributes */
2142 oplock_request, /* oplock_request */
2143 0, /* allocation_size */
2144 0, /* private_flags */
2150 if (!NT_STATUS_IS_OK(status)) {
2151 if (open_was_deferred(req->mid)) {
2152 /* We have re-scheduled this call. */
2155 reply_openerror(req, status);
2159 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2160 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2161 if (!NT_STATUS_IS_OK(status)) {
2162 END_PROFILE(SMBcreate);
2166 reply_outbuf(req, 1, 0);
2167 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2169 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2170 SCVAL(req->outbuf,smb_flg,
2171 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2174 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2175 SCVAL(req->outbuf,smb_flg,
2176 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2179 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2180 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2181 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2182 (unsigned int)fattr));
2185 TALLOC_FREE(smb_fname);
2186 END_PROFILE(SMBcreate);
2190 /****************************************************************************
2191 Reply to a create temporary file.
2192 ****************************************************************************/
2194 void reply_ctemp(struct smb_request *req)
2196 connection_struct *conn = req->conn;
2197 struct smb_filename *smb_fname = NULL;
2205 TALLOC_CTX *ctx = talloc_tos();
2207 START_PROFILE(SMBctemp);
2210 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2214 fattr = SVAL(req->vwv+0, 0);
2215 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2217 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2218 STR_TERMINATE, &status);
2219 if (!NT_STATUS_IS_OK(status)) {
2220 reply_nterror(req, status);
2224 fname = talloc_asprintf(ctx,
2228 fname = talloc_strdup(ctx, "TMXXXXXX");
2232 reply_nterror(req, NT_STATUS_NO_MEMORY);
2236 status = filename_convert(ctx, conn,
2237 req->flags2 & FLAGS2_DFS_PATHNAMES,
2242 if (!NT_STATUS_IS_OK(status)) {
2243 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2244 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2245 ERRSRV, ERRbadpath);
2248 reply_nterror(req, status);
2252 tmpfd = mkstemp(smb_fname->base_name);
2254 reply_nterror(req, map_nt_error_from_unix(errno));
2258 SMB_VFS_STAT(conn, smb_fname);
2260 /* We should fail if file does not exist. */
2261 status = SMB_VFS_CREATE_FILE(
2264 0, /* root_dir_fid */
2265 smb_fname, /* fname */
2266 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2267 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2268 FILE_OPEN, /* create_disposition*/
2269 0, /* create_options */
2270 fattr, /* file_attributes */
2271 oplock_request, /* oplock_request */
2272 0, /* allocation_size */
2273 0, /* private_flags */
2279 /* close fd from mkstemp() */
2282 if (!NT_STATUS_IS_OK(status)) {
2283 if (open_was_deferred(req->mid)) {
2284 /* We have re-scheduled this call. */
2287 reply_openerror(req, status);
2291 reply_outbuf(req, 1, 0);
2292 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2294 /* the returned filename is relative to the directory */
2295 s = strrchr_m(fsp->fsp_name->base_name, '/');
2297 s = fsp->fsp_name->base_name;
2303 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2304 thing in the byte section. JRA */
2305 SSVALS(p, 0, -1); /* what is this? not in spec */
2307 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2309 reply_nterror(req, NT_STATUS_NO_MEMORY);
2313 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2314 SCVAL(req->outbuf, smb_flg,
2315 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2318 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2319 SCVAL(req->outbuf, smb_flg,
2320 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2323 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2324 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2325 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2327 TALLOC_FREE(smb_fname);
2328 END_PROFILE(SMBctemp);
2332 /*******************************************************************
2333 Check if a user is allowed to rename a file.
2334 ********************************************************************/
2336 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2341 if (!CAN_WRITE(conn)) {
2342 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2345 fmode = dos_mode(conn, fsp->fsp_name);
2346 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2347 return NT_STATUS_NO_SUCH_FILE;
2350 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2351 if (fsp->posix_open) {
2352 return NT_STATUS_OK;
2355 /* If no pathnames are open below this
2356 directory, allow the rename. */
2358 if (file_find_subpath(fsp)) {
2359 return NT_STATUS_ACCESS_DENIED;
2361 return NT_STATUS_OK;
2364 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2365 return NT_STATUS_OK;
2368 return NT_STATUS_ACCESS_DENIED;
2371 /*******************************************************************
2372 * unlink a file with all relevant access checks
2373 *******************************************************************/
2375 static NTSTATUS do_unlink(connection_struct *conn,
2376 struct smb_request *req,
2377 struct smb_filename *smb_fname,
2382 uint32 dirtype_orig = dirtype;
2385 bool posix_paths = lp_posix_pathnames();
2387 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2388 smb_fname_str_dbg(smb_fname),
2391 if (!CAN_WRITE(conn)) {
2392 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2396 ret = SMB_VFS_LSTAT(conn, smb_fname);
2398 ret = SMB_VFS_STAT(conn, smb_fname);
2401 return map_nt_error_from_unix(errno);
2404 fattr = dos_mode(conn, smb_fname);
2406 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2407 dirtype = aDIR|aARCH|aRONLY;
2410 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2412 return NT_STATUS_NO_SUCH_FILE;
2415 if (!dir_check_ftype(conn, fattr, dirtype)) {
2417 return NT_STATUS_FILE_IS_A_DIRECTORY;
2419 return NT_STATUS_NO_SUCH_FILE;
2422 if (dirtype_orig & 0x8000) {
2423 /* These will never be set for POSIX. */
2424 return NT_STATUS_NO_SUCH_FILE;
2428 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2429 return NT_STATUS_FILE_IS_A_DIRECTORY;
2432 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2433 return NT_STATUS_NO_SUCH_FILE;
2436 if (dirtype & 0xFF00) {
2437 /* These will never be set for POSIX. */
2438 return NT_STATUS_NO_SUCH_FILE;
2443 return NT_STATUS_NO_SUCH_FILE;
2446 /* Can't delete a directory. */
2448 return NT_STATUS_FILE_IS_A_DIRECTORY;
2453 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2454 return NT_STATUS_OBJECT_NAME_INVALID;
2455 #endif /* JRATEST */
2457 /* On open checks the open itself will check the share mode, so
2458 don't do it here as we'll get it wrong. */
2460 status = SMB_VFS_CREATE_FILE
2463 0, /* root_dir_fid */
2464 smb_fname, /* fname */
2465 DELETE_ACCESS, /* access_mask */
2466 FILE_SHARE_NONE, /* share_access */
2467 FILE_OPEN, /* create_disposition*/
2468 FILE_NON_DIRECTORY_FILE, /* create_options */
2469 /* file_attributes */
2470 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2471 FILE_ATTRIBUTE_NORMAL,
2472 0, /* oplock_request */
2473 0, /* allocation_size */
2474 0, /* private_flags */
2480 if (!NT_STATUS_IS_OK(status)) {
2481 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2482 nt_errstr(status)));
2486 status = can_set_delete_on_close(fsp, fattr);
2487 if (!NT_STATUS_IS_OK(status)) {
2488 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2490 smb_fname_str_dbg(smb_fname),
2491 nt_errstr(status)));
2492 close_file(req, fsp, NORMAL_CLOSE);
2496 /* The set is across all open files on this dev/inode pair. */
2497 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2498 close_file(req, fsp, NORMAL_CLOSE);
2499 return NT_STATUS_ACCESS_DENIED;
2502 return close_file(req, fsp, NORMAL_CLOSE);
2505 /****************************************************************************
2506 The guts of the unlink command, split out so it may be called by the NT SMB
2508 ****************************************************************************/
2510 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2511 uint32 dirtype, struct smb_filename *smb_fname,
2514 char *fname_dir = NULL;
2515 char *fname_mask = NULL;
2517 NTSTATUS status = NT_STATUS_OK;
2518 TALLOC_CTX *ctx = talloc_tos();
2520 /* Split up the directory from the filename/mask. */
2521 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2522 &fname_dir, &fname_mask);
2523 if (!NT_STATUS_IS_OK(status)) {
2528 * We should only check the mangled cache
2529 * here if unix_convert failed. This means
2530 * that the path in 'mask' doesn't exist
2531 * on the file system and so we need to look
2532 * for a possible mangle. This patch from
2533 * Tine Smukavec <valentin.smukavec@hermes.si>.
2536 if (!VALID_STAT(smb_fname->st) &&
2537 mangle_is_mangled(fname_mask, conn->params)) {
2538 char *new_mask = NULL;
2539 mangle_lookup_name_from_8_3(ctx, fname_mask,
2540 &new_mask, conn->params);
2542 TALLOC_FREE(fname_mask);
2543 fname_mask = new_mask;
2550 * Only one file needs to be unlinked. Append the mask back
2551 * onto the directory.
2553 TALLOC_FREE(smb_fname->base_name);
2554 smb_fname->base_name = talloc_asprintf(smb_fname,
2558 if (!smb_fname->base_name) {
2559 status = NT_STATUS_NO_MEMORY;
2563 dirtype = FILE_ATTRIBUTE_NORMAL;
2566 status = check_name(conn, smb_fname->base_name);
2567 if (!NT_STATUS_IS_OK(status)) {
2571 status = do_unlink(conn, req, smb_fname, dirtype);
2572 if (!NT_STATUS_IS_OK(status)) {
2578 struct smb_Dir *dir_hnd = NULL;
2580 const char *dname = NULL;
2581 char *talloced = NULL;
2583 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2584 status = NT_STATUS_OBJECT_NAME_INVALID;
2588 if (strequal(fname_mask,"????????.???")) {
2589 TALLOC_FREE(fname_mask);
2590 fname_mask = talloc_strdup(ctx, "*");
2592 status = NT_STATUS_NO_MEMORY;
2597 status = check_name(conn, fname_dir);
2598 if (!NT_STATUS_IS_OK(status)) {
2602 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2604 if (dir_hnd == NULL) {
2605 status = map_nt_error_from_unix(errno);
2609 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2610 the pattern matches against the long name, otherwise the short name
2611 We don't implement this yet XXXX
2614 status = NT_STATUS_NO_SUCH_FILE;
2616 while ((dname = ReadDirName(dir_hnd, &offset,
2617 &smb_fname->st, &talloced))) {
2618 TALLOC_CTX *frame = talloc_stackframe();
2620 if (!is_visible_file(conn, fname_dir, dname,
2621 &smb_fname->st, true)) {
2623 TALLOC_FREE(talloced);
2627 /* Quick check for "." and ".." */
2628 if (ISDOT(dname) || ISDOTDOT(dname)) {
2630 TALLOC_FREE(talloced);
2634 if(!mask_match(dname, fname_mask,
2635 conn->case_sensitive)) {
2637 TALLOC_FREE(talloced);
2641 TALLOC_FREE(smb_fname->base_name);
2642 smb_fname->base_name =
2643 talloc_asprintf(smb_fname, "%s/%s",
2646 if (!smb_fname->base_name) {
2647 TALLOC_FREE(dir_hnd);
2648 status = NT_STATUS_NO_MEMORY;
2650 TALLOC_FREE(talloced);
2654 status = check_name(conn, smb_fname->base_name);
2655 if (!NT_STATUS_IS_OK(status)) {
2656 TALLOC_FREE(dir_hnd);
2658 TALLOC_FREE(talloced);
2662 status = do_unlink(conn, req, smb_fname, dirtype);
2663 if (!NT_STATUS_IS_OK(status)) {
2665 TALLOC_FREE(talloced);
2670 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2671 smb_fname->base_name));
2674 TALLOC_FREE(talloced);
2676 TALLOC_FREE(dir_hnd);
2679 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2680 status = map_nt_error_from_unix(errno);
2684 TALLOC_FREE(fname_dir);
2685 TALLOC_FREE(fname_mask);
2689 /****************************************************************************
2691 ****************************************************************************/
2693 void reply_unlink(struct smb_request *req)
2695 connection_struct *conn = req->conn;
2697 struct smb_filename *smb_fname = NULL;
2700 bool path_contains_wcard = False;
2701 TALLOC_CTX *ctx = talloc_tos();
2703 START_PROFILE(SMBunlink);
2706 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2710 dirtype = SVAL(req->vwv+0, 0);
2712 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2713 STR_TERMINATE, &status,
2714 &path_contains_wcard);
2715 if (!NT_STATUS_IS_OK(status)) {
2716 reply_nterror(req, status);
2720 status = filename_convert(ctx, conn,
2721 req->flags2 & FLAGS2_DFS_PATHNAMES,
2723 UCF_COND_ALLOW_WCARD_LCOMP,
2724 &path_contains_wcard,
2726 if (!NT_STATUS_IS_OK(status)) {
2727 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2728 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2729 ERRSRV, ERRbadpath);
2732 reply_nterror(req, status);
2736 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2738 status = unlink_internals(conn, req, dirtype, smb_fname,
2739 path_contains_wcard);
2740 if (!NT_STATUS_IS_OK(status)) {
2741 if (open_was_deferred(req->mid)) {
2742 /* We have re-scheduled this call. */
2745 reply_nterror(req, status);
2749 reply_outbuf(req, 0, 0);
2751 TALLOC_FREE(smb_fname);
2752 END_PROFILE(SMBunlink);
2756 /****************************************************************************
2758 ****************************************************************************/
2760 static void fail_readraw(void)
2762 const char *errstr = talloc_asprintf(talloc_tos(),
2763 "FAIL ! reply_readbraw: socket write fail (%s)",
2768 exit_server_cleanly(errstr);
2771 /****************************************************************************
2772 Fake (read/write) sendfile. Returns -1 on read or write fail.
2773 ****************************************************************************/
2775 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2779 size_t tosend = nread;
2786 bufsize = MIN(nread, 65536);
2788 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2792 while (tosend > 0) {
2796 if (tosend > bufsize) {
2801 ret = read_file(fsp,buf,startpos,cur_read);
2807 /* If we had a short read, fill with zeros. */
2808 if (ret < cur_read) {
2809 memset(buf + ret, '\0', cur_read - ret);
2812 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2817 startpos += cur_read;
2821 return (ssize_t)nread;
2824 #if defined(WITH_SENDFILE)
2825 /****************************************************************************
2826 Deal with the case of sendfile reading less bytes from the file than
2827 requested. Fill with zeros (all we can do).
2828 ****************************************************************************/
2830 static void sendfile_short_send(files_struct *fsp,
2835 #define SHORT_SEND_BUFSIZE 1024
2836 if (nread < headersize) {
2837 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2838 "header for file %s (%s). Terminating\n",
2839 fsp_str_dbg(fsp), strerror(errno)));
2840 exit_server_cleanly("sendfile_short_send failed");
2843 nread -= headersize;
2845 if (nread < smb_maxcnt) {
2846 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2848 exit_server_cleanly("sendfile_short_send: "
2852 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2853 "with zeros !\n", fsp_str_dbg(fsp)));
2855 while (nread < smb_maxcnt) {
2857 * We asked for the real file size and told sendfile
2858 * to not go beyond the end of the file. But it can
2859 * happen that in between our fstat call and the
2860 * sendfile call the file was truncated. This is very
2861 * bad because we have already announced the larger
2862 * number of bytes to the client.
2864 * The best we can do now is to send 0-bytes, just as
2865 * a read from a hole in a sparse file would do.
2867 * This should happen rarely enough that I don't care
2868 * about efficiency here :-)
2872 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2873 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2874 exit_server_cleanly("sendfile_short_send: "
2875 "write_data failed");
2882 #endif /* defined WITH_SENDFILE */
2884 /****************************************************************************
2885 Return a readbraw error (4 bytes of zero).
2886 ****************************************************************************/
2888 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2894 smbd_lock_socket(sconn);
2895 if (write_data(smbd_server_fd(),header,4) != 4) {
2898 smbd_unlock_socket(sconn);
2901 /****************************************************************************
2902 Use sendfile in readbraw.
2903 ****************************************************************************/
2905 static void send_file_readbraw(connection_struct *conn,
2906 struct smb_request *req,
2912 struct smbd_server_connection *sconn = req->sconn;
2913 char *outbuf = NULL;
2916 #if defined(WITH_SENDFILE)
2918 * We can only use sendfile on a non-chained packet
2919 * but we can use on a non-oplocked file. tridge proved this
2920 * on a train in Germany :-). JRA.
2921 * reply_readbraw has already checked the length.
2924 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2925 (fsp->wcp == NULL) &&
2926 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
2927 ssize_t sendfile_read = -1;
2929 DATA_BLOB header_blob;
2931 _smb_setlen(header,nread);
2932 header_blob = data_blob_const(header, 4);
2934 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2935 &header_blob, startpos, nread)) == -1) {
2936 /* Returning ENOSYS means no data at all was sent.
2937 * Do this as a normal read. */
2938 if (errno == ENOSYS) {
2939 goto normal_readbraw;
2943 * Special hack for broken Linux with no working sendfile. If we
2944 * return EINTR we sent the header but not the rest of the data.
2945 * Fake this up by doing read/write calls.
2947 if (errno == EINTR) {
2948 /* Ensure we don't do this again. */
2949 set_use_sendfile(SNUM(conn), False);
2950 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2952 if (fake_sendfile(fsp, startpos, nread) == -1) {
2953 DEBUG(0,("send_file_readbraw: "
2954 "fake_sendfile failed for "
2958 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2963 DEBUG(0,("send_file_readbraw: sendfile failed for "
2964 "file %s (%s). Terminating\n",
2965 fsp_str_dbg(fsp), strerror(errno)));
2966 exit_server_cleanly("send_file_readbraw sendfile failed");
2967 } else if (sendfile_read == 0) {
2969 * Some sendfile implementations return 0 to indicate
2970 * that there was a short read, but nothing was
2971 * actually written to the socket. In this case,
2972 * fallback to the normal read path so the header gets
2973 * the correct byte count.
2975 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2976 "bytes falling back to the normal read: "
2977 "%s\n", fsp_str_dbg(fsp)));
2978 goto normal_readbraw;
2981 /* Deal with possible short send. */
2982 if (sendfile_read != 4+nread) {
2983 sendfile_short_send(fsp, sendfile_read, 4, nread);
2991 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2993 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2994 (unsigned)(nread+4)));
2995 reply_readbraw_error(sconn);
3000 ret = read_file(fsp,outbuf+4,startpos,nread);
3001 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3010 _smb_setlen(outbuf,ret);
3011 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3014 TALLOC_FREE(outbuf);
3017 /****************************************************************************
3018 Reply to a readbraw (core+ protocol).
3019 ****************************************************************************/
3021 void reply_readbraw(struct smb_request *req)
3023 connection_struct *conn = req->conn;
3024 struct smbd_server_connection *sconn = req->sconn;
3025 ssize_t maxcount,mincount;
3029 struct lock_struct lock;
3032 START_PROFILE(SMBreadbraw);
3034 if (srv_is_signing_active(sconn) ||
3035 is_encrypted_packet(req->inbuf)) {
3036 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3037 "raw reads/writes are disallowed.");
3041 reply_readbraw_error(sconn);
3042 END_PROFILE(SMBreadbraw);
3046 if (sconn->smb1.echo_handler.trusted_fde) {
3047 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3048 "'async smb echo handler = yes'\n"));
3049 reply_readbraw_error(sconn);
3050 END_PROFILE(SMBreadbraw);
3055 * Special check if an oplock break has been issued
3056 * and the readraw request croses on the wire, we must
3057 * return a zero length response here.
3060 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3063 * We have to do a check_fsp by hand here, as
3064 * we must always return 4 zero bytes on error,
3068 if (!fsp || !conn || conn != fsp->conn ||
3069 req->vuid != fsp->vuid ||
3070 fsp->is_directory || fsp->fh->fd == -1) {
3072 * fsp could be NULL here so use the value from the packet. JRA.
3074 DEBUG(3,("reply_readbraw: fnum %d not valid "
3076 (int)SVAL(req->vwv+0, 0)));
3077 reply_readbraw_error(sconn);
3078 END_PROFILE(SMBreadbraw);
3082 /* Do a "by hand" version of CHECK_READ. */
3083 if (!(fsp->can_read ||
3084 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3085 (fsp->access_mask & FILE_EXECUTE)))) {
3086 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3087 (int)SVAL(req->vwv+0, 0)));
3088 reply_readbraw_error(sconn);
3089 END_PROFILE(SMBreadbraw);
3093 flush_write_cache(fsp, READRAW_FLUSH);
3095 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3096 if(req->wct == 10) {
3098 * This is a large offset (64 bit) read.
3100 #ifdef LARGE_SMB_OFF_T
3102 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3104 #else /* !LARGE_SMB_OFF_T */
3107 * Ensure we haven't been sent a >32 bit offset.
3110 if(IVAL(req->vwv+8, 0) != 0) {
3111 DEBUG(0,("reply_readbraw: large offset "
3112 "(%x << 32) used and we don't support "
3113 "64 bit offsets.\n",
3114 (unsigned int)IVAL(req->vwv+8, 0) ));
3115 reply_readbraw_error();
3116 END_PROFILE(SMBreadbraw);
3120 #endif /* LARGE_SMB_OFF_T */
3123 DEBUG(0,("reply_readbraw: negative 64 bit "
3124 "readraw offset (%.0f) !\n",
3125 (double)startpos ));
3126 reply_readbraw_error(sconn);
3127 END_PROFILE(SMBreadbraw);
3132 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3133 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3135 /* ensure we don't overrun the packet size */
3136 maxcount = MIN(65535,maxcount);
3138 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3139 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3142 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3143 reply_readbraw_error(sconn);
3144 END_PROFILE(SMBreadbraw);
3148 if (fsp_stat(fsp) == 0) {
3149 size = fsp->fsp_name->st.st_ex_size;
3152 if (startpos >= size) {
3155 nread = MIN(maxcount,(size - startpos));
3158 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3159 if (nread < mincount)
3163 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3164 "min=%lu nread=%lu\n",
3165 fsp->fnum, (double)startpos,
3166 (unsigned long)maxcount,
3167 (unsigned long)mincount,
3168 (unsigned long)nread ) );
3170 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3172 DEBUG(5,("reply_readbraw finished\n"));
3174 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3176 END_PROFILE(SMBreadbraw);
3181 #define DBGC_CLASS DBGC_LOCKING
3183 /****************************************************************************
3184 Reply to a lockread (core+ protocol).
3185 ****************************************************************************/
3187 void reply_lockread(struct smb_request *req)
3189 connection_struct *conn = req->conn;
3196 struct byte_range_lock *br_lck = NULL;
3198 struct smbd_server_connection *sconn = req->sconn;
3200 START_PROFILE(SMBlockread);
3203 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3204 END_PROFILE(SMBlockread);
3208 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3210 if (!check_fsp(conn, req, fsp)) {
3211 END_PROFILE(SMBlockread);
3215 if (!CHECK_READ(fsp,req)) {
3216 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3217 END_PROFILE(SMBlockread);
3221 numtoread = SVAL(req->vwv+1, 0);
3222 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3224 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3226 reply_outbuf(req, 5, numtoread + 3);
3228 data = smb_buf(req->outbuf) + 3;
3231 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3232 * protocol request that predates the read/write lock concept.
3233 * Thus instead of asking for a read lock here we need to ask
3234 * for a write lock. JRA.
3235 * Note that the requested lock size is unaffected by max_recv.
3238 br_lck = do_lock(req->sconn->msg_ctx,
3240 (uint64_t)req->smbpid,
3241 (uint64_t)numtoread,
3245 False, /* Non-blocking lock. */
3249 TALLOC_FREE(br_lck);
3251 if (NT_STATUS_V(status)) {
3252 reply_nterror(req, status);
3253 END_PROFILE(SMBlockread);
3258 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3261 if (numtoread > sconn->smb1.negprot.max_recv) {
3262 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3263 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3264 (unsigned int)numtoread,
3265 (unsigned int)sconn->smb1.negprot.max_recv));
3266 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3268 nread = read_file(fsp,data,startpos,numtoread);
3271 reply_nterror(req, map_nt_error_from_unix(errno));
3272 END_PROFILE(SMBlockread);
3276 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3278 SSVAL(req->outbuf,smb_vwv0,nread);
3279 SSVAL(req->outbuf,smb_vwv5,nread+3);
3280 p = smb_buf(req->outbuf);
3281 SCVAL(p,0,0); /* pad byte. */
3284 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3285 fsp->fnum, (int)numtoread, (int)nread));
3287 END_PROFILE(SMBlockread);
3292 #define DBGC_CLASS DBGC_ALL
3294 /****************************************************************************
3296 ****************************************************************************/
3298 void reply_read(struct smb_request *req)
3300 connection_struct *conn = req->conn;
3307 struct lock_struct lock;
3308 struct smbd_server_connection *sconn = req->sconn;
3310 START_PROFILE(SMBread);
3313 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3314 END_PROFILE(SMBread);
3318 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3320 if (!check_fsp(conn, req, fsp)) {
3321 END_PROFILE(SMBread);
3325 if (!CHECK_READ(fsp,req)) {
3326 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3327 END_PROFILE(SMBread);
3331 numtoread = SVAL(req->vwv+1, 0);
3332 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3334 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3337 * The requested read size cannot be greater than max_recv. JRA.
3339 if (numtoread > sconn->smb1.negprot.max_recv) {
3340 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3341 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3342 (unsigned int)numtoread,
3343 (unsigned int)sconn->smb1.negprot.max_recv));
3344 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3347 reply_outbuf(req, 5, numtoread+3);
3349 data = smb_buf(req->outbuf) + 3;
3351 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3352 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3355 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3356 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3357 END_PROFILE(SMBread);
3362 nread = read_file(fsp,data,startpos,numtoread);
3365 reply_nterror(req, map_nt_error_from_unix(errno));
3369 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3371 SSVAL(req->outbuf,smb_vwv0,nread);
3372 SSVAL(req->outbuf,smb_vwv5,nread+3);
3373 SCVAL(smb_buf(req->outbuf),0,1);
3374 SSVAL(smb_buf(req->outbuf),1,nread);
3376 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3377 fsp->fnum, (int)numtoread, (int)nread ) );
3380 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3382 END_PROFILE(SMBread);
3386 /****************************************************************************
3388 ****************************************************************************/
3390 static int setup_readX_header(struct smb_request *req, char *outbuf,
3396 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3397 data = smb_buf(outbuf);
3399 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3401 SCVAL(outbuf,smb_vwv0,0xFF);
3402 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3403 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3404 SSVAL(outbuf,smb_vwv6,
3406 + 1 /* the wct field */
3407 + 12 * sizeof(uint16_t) /* vwv */
3408 + 2); /* the buflen field */
3409 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3410 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3411 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3412 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3416 /****************************************************************************
3417 Reply to a read and X - possibly using sendfile.
3418 ****************************************************************************/
3420 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3421 files_struct *fsp, SMB_OFF_T startpos,
3425 struct lock_struct lock;
3426 int saved_errno = 0;
3428 if(fsp_stat(fsp) == -1) {
3429 reply_nterror(req, map_nt_error_from_unix(errno));
3433 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3434 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3437 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3438 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3442 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3443 (startpos > fsp->fsp_name->st.st_ex_size)
3444 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3446 * We already know that we would do a short read, so don't
3447 * try the sendfile() path.
3449 goto nosendfile_read;
3452 #if defined(WITH_SENDFILE)
3454 * We can only use sendfile on a non-chained packet
3455 * but we can use on a non-oplocked file. tridge proved this
3456 * on a train in Germany :-). JRA.
3459 if (!req_is_in_chain(req) &&
3460 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3461 (fsp->wcp == NULL) &&
3462 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3463 uint8 headerbuf[smb_size + 12 * 2];
3467 * Set up the packet header before send. We
3468 * assume here the sendfile will work (get the
3469 * correct amount of data).
3472 header = data_blob_const(headerbuf, sizeof(headerbuf));
3474 construct_reply_common_req(req, (char *)headerbuf);
3475 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3477 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3478 /* Returning ENOSYS means no data at all was sent.
3479 Do this as a normal read. */
3480 if (errno == ENOSYS) {
3485 * Special hack for broken Linux with no working sendfile. If we
3486 * return EINTR we sent the header but not the rest of the data.
3487 * Fake this up by doing read/write calls.
3490 if (errno == EINTR) {
3491 /* Ensure we don't do this again. */
3492 set_use_sendfile(SNUM(conn), False);
3493 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3494 nread = fake_sendfile(fsp, startpos,
3497 DEBUG(0,("send_file_readX: "
3498 "fake_sendfile failed for "
3502 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3504 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3505 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3506 /* No outbuf here means successful sendfile. */
3510 DEBUG(0,("send_file_readX: sendfile failed for file "
3511 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3513 exit_server_cleanly("send_file_readX sendfile failed");
3514 } else if (nread == 0) {
3516 * Some sendfile implementations return 0 to indicate
3517 * that there was a short read, but nothing was
3518 * actually written to the socket. In this case,
3519 * fallback to the normal read path so the header gets
3520 * the correct byte count.
3522 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3523 "falling back to the normal read: %s\n",
3528 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3529 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3531 /* Deal with possible short send. */
3532 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3533 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3535 /* No outbuf here means successful sendfile. */
3536 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3537 SMB_PERFCOUNT_END(&req->pcd);
3545 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3546 uint8 headerbuf[smb_size + 2*12];
3548 construct_reply_common_req(req, (char *)headerbuf);
3549 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3551 /* Send out the header. */
3552 if (write_data(smbd_server_fd(), (char *)headerbuf,
3553 sizeof(headerbuf)) != sizeof(headerbuf)) {
3554 DEBUG(0,("send_file_readX: write_data failed for file "
3555 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3557 exit_server_cleanly("send_file_readX sendfile failed");
3559 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3561 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3562 "file %s (%s).\n", fsp_str_dbg(fsp),
3564 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3571 reply_outbuf(req, 12, smb_maxcnt);
3573 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3574 saved_errno = errno;
3576 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3579 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3583 setup_readX_header(req, (char *)req->outbuf, nread);
3585 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3586 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3592 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3593 TALLOC_FREE(req->outbuf);
3597 /****************************************************************************
3598 Reply to a read and X.
3599 ****************************************************************************/
3601 void reply_read_and_X(struct smb_request *req)
3603 connection_struct *conn = req->conn;
3607 bool big_readX = False;
3609 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3612 START_PROFILE(SMBreadX);
3614 if ((req->wct != 10) && (req->wct != 12)) {
3615 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3619 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3620 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3621 smb_maxcnt = SVAL(req->vwv+5, 0);
3623 /* If it's an IPC, pass off the pipe handler. */
3625 reply_pipe_read_and_X(req);
3626 END_PROFILE(SMBreadX);
3630 if (!check_fsp(conn, req, fsp)) {
3631 END_PROFILE(SMBreadX);
3635 if (!CHECK_READ(fsp,req)) {
3636 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3637 END_PROFILE(SMBreadX);
3641 if (global_client_caps & CAP_LARGE_READX) {
3642 size_t upper_size = SVAL(req->vwv+7, 0);
3643 smb_maxcnt |= (upper_size<<16);
3644 if (upper_size > 1) {
3645 /* Can't do this on a chained packet. */
3646 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3647 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3648 END_PROFILE(SMBreadX);
3651 /* We currently don't do this on signed or sealed data. */
3652 if (srv_is_signing_active(req->sconn) ||
3653 is_encrypted_packet(req->inbuf)) {
3654 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3655 END_PROFILE(SMBreadX);
3658 /* Is there room in the reply for this data ? */
3659 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3661 NT_STATUS_INVALID_PARAMETER);
3662 END_PROFILE(SMBreadX);
3669 if (req->wct == 12) {
3670 #ifdef LARGE_SMB_OFF_T
3672 * This is a large offset (64 bit) read.
3674 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3676 #else /* !LARGE_SMB_OFF_T */
3679 * Ensure we haven't been sent a >32 bit offset.
3682 if(IVAL(req->vwv+10, 0) != 0) {
3683 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3684 "used and we don't support 64 bit offsets.\n",
3685 (unsigned int)IVAL(req->vwv+10, 0) ));
3686 END_PROFILE(SMBreadX);
3687 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3691 #endif /* LARGE_SMB_OFF_T */
3696 NTSTATUS status = schedule_aio_read_and_X(conn,
3701 if (NT_STATUS_IS_OK(status)) {
3702 /* Read scheduled - we're done. */
3705 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3706 /* Real error - report to client. */
3707 END_PROFILE(SMBreadX);
3708 reply_nterror(req, status);
3711 /* NT_STATUS_RETRY - fall back to sync read. */
3714 smbd_lock_socket(req->sconn);
3715 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3716 smbd_unlock_socket(req->sconn);
3719 END_PROFILE(SMBreadX);
3723 /****************************************************************************
3724 Error replies to writebraw must have smb_wct == 1. Fix this up.
3725 ****************************************************************************/
3727 void error_to_writebrawerr(struct smb_request *req)
3729 uint8 *old_outbuf = req->outbuf;
3731 reply_outbuf(req, 1, 0);
3733 memcpy(req->outbuf, old_outbuf, smb_size);
3734 TALLOC_FREE(old_outbuf);
3737 /****************************************************************************
3738 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3739 ****************************************************************************/
3741 void reply_writebraw(struct smb_request *req)
3743 connection_struct *conn = req->conn;
3746 ssize_t total_written=0;
3747 size_t numtowrite=0;
3753 struct lock_struct lock;
3756 START_PROFILE(SMBwritebraw);
3759 * If we ever reply with an error, it must have the SMB command
3760 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3763 SCVAL(req->inbuf,smb_com,SMBwritec);
3765 if (srv_is_signing_active(req->sconn)) {
3766 END_PROFILE(SMBwritebraw);
3767 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3768 "raw reads/writes are disallowed.");
3771 if (req->wct < 12) {
3772 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3773 error_to_writebrawerr(req);
3774 END_PROFILE(SMBwritebraw);
3778 if (req->sconn->smb1.echo_handler.trusted_fde) {
3779 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3780 "'async smb echo handler = yes'\n"));
3781 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3782 error_to_writebrawerr(req);
3783 END_PROFILE(SMBwritebraw);
3787 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3788 if (!check_fsp(conn, req, fsp)) {
3789 error_to_writebrawerr(req);
3790 END_PROFILE(SMBwritebraw);
3794 if (!CHECK_WRITE(fsp)) {
3795 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3796 error_to_writebrawerr(req);
3797 END_PROFILE(SMBwritebraw);
3801 tcount = IVAL(req->vwv+1, 0);
3802 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3803 write_through = BITSETW(req->vwv+7,0);
3805 /* We have to deal with slightly different formats depending
3806 on whether we are using the core+ or lanman1.0 protocol */
3808 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3809 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3810 data = smb_buf(req->inbuf);
3812 numtowrite = SVAL(req->vwv+10, 0);
3813 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3816 /* Ensure we don't write bytes past the end of this packet. */
3817 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3818 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3819 error_to_writebrawerr(req);
3820 END_PROFILE(SMBwritebraw);
3824 if (!fsp->print_file) {
3825 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3826 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3829 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3830 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3831 error_to_writebrawerr(req);
3832 END_PROFILE(SMBwritebraw);
3838 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3841 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3842 "wrote=%d sync=%d\n",
3843 fsp->fnum, (double)startpos, (int)numtowrite,
3844 (int)nwritten, (int)write_through));
3846 if (nwritten < (ssize_t)numtowrite) {
3847 reply_nterror(req, NT_STATUS_DISK_FULL);
3848 error_to_writebrawerr(req);
3852 total_written = nwritten;
3854 /* Allocate a buffer of 64k + length. */
3855 buf = TALLOC_ARRAY(NULL, char, 65540);
3857 reply_nterror(req, NT_STATUS_NO_MEMORY);
3858 error_to_writebrawerr(req);
3862 /* Return a SMBwritebraw message to the redirector to tell
3863 * it to send more bytes */
3865 memcpy(buf, req->inbuf, smb_size);
3866 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3867 SCVAL(buf,smb_com,SMBwritebraw);
3868 SSVALS(buf,smb_vwv0,0xFFFF);
3870 if (!srv_send_smb(smbd_server_fd(),
3872 false, 0, /* no signing */
3873 IS_CONN_ENCRYPTED(conn),
3875 exit_server_cleanly("reply_writebraw: srv_send_smb "
3879 /* Now read the raw data into the buffer and write it */
3880 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3882 if (!NT_STATUS_IS_OK(status)) {
3883 exit_server_cleanly("secondary writebraw failed");
3886 /* Set up outbuf to return the correct size */
3887 reply_outbuf(req, 1, 0);
3889 if (numtowrite != 0) {
3891 if (numtowrite > 0xFFFF) {
3892 DEBUG(0,("reply_writebraw: Oversize secondary write "
3893 "raw requested (%u). Terminating\n",
3894 (unsigned int)numtowrite ));
3895 exit_server_cleanly("secondary writebraw failed");
3898 if (tcount > nwritten+numtowrite) {
3899 DEBUG(3,("reply_writebraw: Client overestimated the "
3901 (int)tcount,(int)nwritten,(int)numtowrite));
3904 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3906 if (!NT_STATUS_IS_OK(status)) {
3907 DEBUG(0,("reply_writebraw: Oversize secondary write "
3908 "raw read failed (%s). Terminating\n",
3909 nt_errstr(status)));
3910 exit_server_cleanly("secondary writebraw failed");
3913 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3914 if (nwritten == -1) {
3916 reply_nterror(req, map_nt_error_from_unix(errno));
3917 error_to_writebrawerr(req);
3921 if (nwritten < (ssize_t)numtowrite) {
3922 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3923 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3927 total_written += nwritten;
3932 SSVAL(req->outbuf,smb_vwv0,total_written);
3934 status = sync_file(conn, fsp, write_through);
3935 if (!NT_STATUS_IS_OK(status)) {
3936 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3937 fsp_str_dbg(fsp), nt_errstr(status)));
3938 reply_nterror(req, status);
3939 error_to_writebrawerr(req);
3943 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3945 fsp->fnum, (double)startpos, (int)numtowrite,
3946 (int)total_written));
3948 if (!fsp->print_file) {
3949 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3952 /* We won't return a status if write through is not selected - this
3953 * follows what WfWg does */
3954 END_PROFILE(SMBwritebraw);
3956 if (!write_through && total_written==tcount) {
3958 #if RABBIT_PELLET_FIX
3960 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3961 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3964 if (!send_keepalive(smbd_server_fd())) {
3965 exit_server_cleanly("reply_writebraw: send of "
3966 "keepalive failed");
3969 TALLOC_FREE(req->outbuf);
3974 if (!fsp->print_file) {
3975 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3978 END_PROFILE(SMBwritebraw);
3983 #define DBGC_CLASS DBGC_LOCKING
3985 /****************************************************************************
3986 Reply to a writeunlock (core+).
3987 ****************************************************************************/
3989 void reply_writeunlock(struct smb_request *req)
3991 connection_struct *conn = req->conn;
3992 ssize_t nwritten = -1;
3996 NTSTATUS status = NT_STATUS_OK;
3998 struct lock_struct lock;
3999 int saved_errno = 0;
4001 START_PROFILE(SMBwriteunlock);
4004 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4005 END_PROFILE(SMBwriteunlock);
4009 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4011 if (!check_fsp(conn, req, fsp)) {
4012 END_PROFILE(SMBwriteunlock);
4016 if (!CHECK_WRITE(fsp)) {
4017 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4018 END_PROFILE(SMBwriteunlock);
4022 numtowrite = SVAL(req->vwv+1, 0);
4023 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4024 data = (const char *)req->buf + 3;
4026 if (!fsp->print_file && numtowrite > 0) {
4027 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4028 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4031 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4032 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4033 END_PROFILE(SMBwriteunlock);
4038 /* The special X/Open SMB protocol handling of
4039 zero length writes is *NOT* done for
4041 if(numtowrite == 0) {
4044 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4045 saved_errno = errno;
4048 status = sync_file(conn, fsp, False /* write through */);
4049 if (!NT_STATUS_IS_OK(status)) {
4050 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4051 fsp_str_dbg(fsp), nt_errstr(status)));
4052 reply_nterror(req, status);
4057 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4061 if((nwritten < numtowrite) && (numtowrite != 0)) {
4062 reply_nterror(req, NT_STATUS_DISK_FULL);
4066 if (numtowrite && !fsp->print_file) {
4067 status = do_unlock(req->sconn->msg_ctx,
4069 (uint64_t)req->smbpid,
4070 (uint64_t)numtowrite,
4074 if (NT_STATUS_V(status)) {
4075 reply_nterror(req, status);
4080 reply_outbuf(req, 1, 0);
4082 SSVAL(req->outbuf,smb_vwv0,nwritten);
4084 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4085 fsp->fnum, (int)numtowrite, (int)nwritten));
4088 if (numtowrite && !fsp->print_file) {
4089 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4092 END_PROFILE(SMBwriteunlock);
4097 #define DBGC_CLASS DBGC_ALL
4099 /****************************************************************************
4101 ****************************************************************************/
4103 void reply_write(struct smb_request *req)
4105 connection_struct *conn = req->conn;
4107 ssize_t nwritten = -1;
4111 struct lock_struct lock;
4113 int saved_errno = 0;
4115 START_PROFILE(SMBwrite);
4118 END_PROFILE(SMBwrite);
4119 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4123 /* If it's an IPC, pass off the pipe handler. */
4125 reply_pipe_write(req);
4126 END_PROFILE(SMBwrite);
4130 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4132 if (!check_fsp(conn, req, fsp)) {
4133 END_PROFILE(SMBwrite);
4137 if (!CHECK_WRITE(fsp)) {
4138 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4139 END_PROFILE(SMBwrite);
4143 numtowrite = SVAL(req->vwv+1, 0);
4144 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4145 data = (const char *)req->buf + 3;
4147 if (!fsp->print_file) {
4148 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4149 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4152 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4153 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4154 END_PROFILE(SMBwrite);
4160 * X/Open SMB protocol says that if smb_vwv1 is
4161 * zero then the file size should be extended or
4162 * truncated to the size given in smb_vwv[2-3].
4165 if(numtowrite == 0) {
4167 * This is actually an allocate call, and set EOF. JRA.
4169 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4171 reply_nterror(req, NT_STATUS_DISK_FULL);
4174 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4176 reply_nterror(req, NT_STATUS_DISK_FULL);
4179 trigger_write_time_update_immediate(fsp);
4181 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4184 status = sync_file(conn, fsp, False);
4185 if (!NT_STATUS_IS_OK(status)) {
4186 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4187 fsp_str_dbg(fsp), nt_errstr(status)));
4188 reply_nterror(req, status);
4193 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4197 if((nwritten == 0) && (numtowrite != 0)) {
4198 reply_nterror(req, NT_STATUS_DISK_FULL);
4202 reply_outbuf(req, 1, 0);
4204 SSVAL(req->outbuf,smb_vwv0,nwritten);
4206 if (nwritten < (ssize_t)numtowrite) {
4207 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4208 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4211 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4214 if (!fsp->print_file) {
4215 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4218 END_PROFILE(SMBwrite);
4222 /****************************************************************************
4223 Ensure a buffer is a valid writeX for recvfile purposes.
4224 ****************************************************************************/
4226 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4227 (2*14) + /* word count (including bcc) */ \
4230 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4231 const uint8_t *inbuf)
4234 connection_struct *conn = NULL;
4235 unsigned int doff = 0;
4236 size_t len = smb_len_large(inbuf);
4238 if (is_encrypted_packet(inbuf)) {
4239 /* Can't do this on encrypted
4244 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4248 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4249 CVAL(inbuf,smb_wct) != 14) {
4250 DEBUG(10,("is_valid_writeX_buffer: chained or "
4251 "invalid word length.\n"));
4255 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4257 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4261 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4264 if (IS_PRINT(conn)) {
4265 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4268 doff = SVAL(inbuf,smb_vwv11);
4270 numtowrite = SVAL(inbuf,smb_vwv10);
4272 if (len > doff && len - doff > 0xFFFF) {
4273 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4276 if (numtowrite == 0) {
4277 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4281 /* Ensure the sizes match up. */
4282 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4283 /* no pad byte...old smbclient :-( */
4284 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4286 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4290 if (len - doff != numtowrite) {
4291 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4292 "len = %u, doff = %u, numtowrite = %u\n",
4295 (unsigned int)numtowrite ));
4299 DEBUG(10,("is_valid_writeX_buffer: true "
4300 "len = %u, doff = %u, numtowrite = %u\n",
4303 (unsigned int)numtowrite ));
4308 /****************************************************************************
4309 Reply to a write and X.
4310 ****************************************************************************/
4312 void reply_write_and_X(struct smb_request *req)
4314 connection_struct *conn = req->conn;
4316 struct lock_struct lock;
4321 unsigned int smb_doff;
4322 unsigned int smblen;
4325 int saved_errno = 0;
4327 START_PROFILE(SMBwriteX);
4329 if ((req->wct != 12) && (req->wct != 14)) {
4330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4331 END_PROFILE(SMBwriteX);
4335 numtowrite = SVAL(req->vwv+10, 0);
4336 smb_doff = SVAL(req->vwv+11, 0);
4337 smblen = smb_len(req->inbuf);
4339 if (req->unread_bytes > 0xFFFF ||
4340 (smblen > smb_doff &&
4341 smblen - smb_doff > 0xFFFF)) {
4342 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4345 if (req->unread_bytes) {
4346 /* Can't do a recvfile write on IPC$ */
4348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4349 END_PROFILE(SMBwriteX);
4352 if (numtowrite != req->unread_bytes) {
4353 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4354 END_PROFILE(SMBwriteX);
4358 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4359 smb_doff + numtowrite > smblen) {
4360 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4361 END_PROFILE(SMBwriteX);
4366 /* If it's an IPC, pass off the pipe handler. */
4368 if (req->unread_bytes) {
4369 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4370 END_PROFILE(SMBwriteX);
4373 reply_pipe_write_and_X(req);
4374 END_PROFILE(SMBwriteX);
4378 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4379 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4380 write_through = BITSETW(req->vwv+7,0);
4382 if (!check_fsp(conn, req, fsp)) {
4383 END_PROFILE(SMBwriteX);
4387 if (!CHECK_WRITE(fsp)) {
4388 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4389 END_PROFILE(SMBwriteX);
4393 data = smb_base(req->inbuf) + smb_doff;
4395 if(req->wct == 14) {
4396 #ifdef LARGE_SMB_OFF_T
4398 * This is a large offset (64 bit) write.
4400 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4402 #else /* !LARGE_SMB_OFF_T */
4405 * Ensure we haven't been sent a >32 bit offset.
4408 if(IVAL(req->vwv+12, 0) != 0) {
4409 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4410 "used and we don't support 64 bit offsets.\n",
4411 (unsigned int)IVAL(req->vwv+12, 0) ));
4412 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4413 END_PROFILE(SMBwriteX);
4417 #endif /* LARGE_SMB_OFF_T */
4420 /* X/Open SMB protocol says that, unlike SMBwrite
4421 if the length is zero then NO truncation is
4422 done, just a write of zero. To truncate a file,
4425 if(numtowrite == 0) {
4428 if (req->unread_bytes == 0) {
4429 status = schedule_aio_write_and_X(conn,
4436 if (NT_STATUS_IS_OK(status)) {
4437 /* write scheduled - we're done. */
4440 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4441 /* Real error - report to client. */
4442 reply_nterror(req, status);
4445 /* NT_STATUS_RETRY - fall through to sync write. */
4448 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4449 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4452 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4453 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4457 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4458 saved_errno = errno;
4460 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4464 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4468 if((nwritten == 0) && (numtowrite != 0)) {
4469 reply_nterror(req, NT_STATUS_DISK_FULL);
4473 reply_outbuf(req, 6, 0);
4474 SSVAL(req->outbuf,smb_vwv2,nwritten);
4475 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4477 if (nwritten < (ssize_t)numtowrite) {
4478 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4479 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4482 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4483 fsp->fnum, (int)numtowrite, (int)nwritten));
4485 status = sync_file(conn, fsp, write_through);
4486 if (!NT_STATUS_IS_OK(status)) {
4487 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4488 fsp_str_dbg(fsp), nt_errstr(status)));
4489 reply_nterror(req, status);
4493 END_PROFILE(SMBwriteX);
4498 END_PROFILE(SMBwriteX);
4502 /****************************************************************************
4504 ****************************************************************************/
4506 void reply_lseek(struct smb_request *req)
4508 connection_struct *conn = req->conn;
4514 START_PROFILE(SMBlseek);
4517 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4518 END_PROFILE(SMBlseek);
4522 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4524 if (!check_fsp(conn, req, fsp)) {
4528 flush_write_cache(fsp, SEEK_FLUSH);
4530 mode = SVAL(req->vwv+1, 0) & 3;
4531 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4532 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4541 res = fsp->fh->pos + startpos;
4552 if (umode == SEEK_END) {
4553 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4554 if(errno == EINVAL) {
4555 SMB_OFF_T current_pos = startpos;
4557 if(fsp_stat(fsp) == -1) {
4559 map_nt_error_from_unix(errno));
4560 END_PROFILE(SMBlseek);
4564 current_pos += fsp->fsp_name->st.st_ex_size;
4566 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4571 reply_nterror(req, map_nt_error_from_unix(errno));
4572 END_PROFILE(SMBlseek);
4579 reply_outbuf(req, 2, 0);
4580 SIVAL(req->outbuf,smb_vwv0,res);
4582 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4583 fsp->fnum, (double)startpos, (double)res, mode));
4585 END_PROFILE(SMBlseek);
4589 /****************************************************************************
4591 ****************************************************************************/
4593 void reply_flush(struct smb_request *req)
4595 connection_struct *conn = req->conn;
4599 START_PROFILE(SMBflush);
4602 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4606 fnum = SVAL(req->vwv+0, 0);
4607 fsp = file_fsp(req, fnum);
4609 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4614 file_sync_all(conn);
4616 NTSTATUS status = sync_file(conn, fsp, True);
4617 if (!NT_STATUS_IS_OK(status)) {
4618 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4619 fsp_str_dbg(fsp), nt_errstr(status)));
4620 reply_nterror(req, status);
4621 END_PROFILE(SMBflush);
4626 reply_outbuf(req, 0, 0);
4628 DEBUG(3,("flush\n"));
4629 END_PROFILE(SMBflush);
4633 /****************************************************************************
4635 conn POINTER CAN BE NULL HERE !
4636 ****************************************************************************/
4638 void reply_exit(struct smb_request *req)
4640 START_PROFILE(SMBexit);
4642 file_close_pid(req->smbpid, req->vuid);
4644 reply_outbuf(req, 0, 0);
4646 DEBUG(3,("exit\n"));
4648 END_PROFILE(SMBexit);
4652 /****************************************************************************
4653 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4654 ****************************************************************************/
4656 void reply_close(struct smb_request *req)
4658 connection_struct *conn = req->conn;
4659 NTSTATUS status = NT_STATUS_OK;
4660 files_struct *fsp = NULL;
4661 START_PROFILE(SMBclose);
4664 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4665 END_PROFILE(SMBclose);
4669 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4672 * We can only use check_fsp if we know it's not a directory.
4675 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4676 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4677 END_PROFILE(SMBclose);
4681 if(fsp->is_directory) {
4683 * Special case - close NT SMB directory handle.
4685 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4686 status = close_file(req, fsp, NORMAL_CLOSE);
4690 * Close ordinary file.
4693 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4694 fsp->fh->fd, fsp->fnum,
4695 conn->num_files_open));
4698 * Take care of any time sent in the close.
4701 t = srv_make_unix_date3(req->vwv+1);
4702 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4705 * close_file() returns the unix errno if an error
4706 * was detected on close - normally this is due to
4707 * a disk full error. If not then it was probably an I/O error.
4710 status = close_file(req, fsp, NORMAL_CLOSE);
4713 if (!NT_STATUS_IS_OK(status)) {
4714 reply_nterror(req, status);
4715 END_PROFILE(SMBclose);
4719 reply_outbuf(req, 0, 0);
4720 END_PROFILE(SMBclose);
4724 /****************************************************************************
4725 Reply to a writeclose (Core+ protocol).
4726 ****************************************************************************/
4728 void reply_writeclose(struct smb_request *req)
4730 connection_struct *conn = req->conn;
4732 ssize_t nwritten = -1;
4733 NTSTATUS close_status = NT_STATUS_OK;
4736 struct timespec mtime;
4738 struct lock_struct lock;
4740 START_PROFILE(SMBwriteclose);
4743 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4744 END_PROFILE(SMBwriteclose);
4748 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4750 if (!check_fsp(conn, req, fsp)) {
4751 END_PROFILE(SMBwriteclose);
4754 if (!CHECK_WRITE(fsp)) {
4755 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4756 END_PROFILE(SMBwriteclose);
4760 numtowrite = SVAL(req->vwv+1, 0);
4761 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4762 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4763 data = (const char *)req->buf + 1;
4765 if (!fsp->print_file) {
4766 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4767 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4770 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4771 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4772 END_PROFILE(SMBwriteclose);
4777 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4779 set_close_write_time(fsp, mtime);
4782 * More insanity. W2K only closes the file if writelen > 0.
4787 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4788 "file %s\n", fsp_str_dbg(fsp)));
4789 close_status = close_file(req, fsp, NORMAL_CLOSE);
4792 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4793 fsp->fnum, (int)numtowrite, (int)nwritten,
4794 conn->num_files_open));
4796 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4797 reply_nterror(req, NT_STATUS_DISK_FULL);
4801 if(!NT_STATUS_IS_OK(close_status)) {
4802 reply_nterror(req, close_status);
4806 reply_outbuf(req, 1, 0);
4808 SSVAL(req->outbuf,smb_vwv0,nwritten);
4811 if (numtowrite && !fsp->print_file) {
4812 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4815 END_PROFILE(SMBwriteclose);
4820 #define DBGC_CLASS DBGC_LOCKING
4822 /****************************************************************************
4824 ****************************************************************************/
4826 void reply_lock(struct smb_request *req)
4828 connection_struct *conn = req->conn;
4829 uint64_t count,offset;
4832 struct byte_range_lock *br_lck = NULL;
4834 START_PROFILE(SMBlock);
4837 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4838 END_PROFILE(SMBlock);
4842 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4844 if (!check_fsp(conn, req, fsp)) {
4845 END_PROFILE(SMBlock);
4849 count = (uint64_t)IVAL(req->vwv+1, 0);
4850 offset = (uint64_t)IVAL(req->vwv+3, 0);
4852 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4853 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4855 br_lck = do_lock(req->sconn->msg_ctx,
4857 (uint64_t)req->smbpid,
4862 False, /* Non-blocking lock. */
4867 TALLOC_FREE(br_lck);
4869 if (NT_STATUS_V(status)) {
4870 reply_nterror(req, status);
4871 END_PROFILE(SMBlock);
4875 reply_outbuf(req, 0, 0);
4877 END_PROFILE(SMBlock);
4881 /****************************************************************************
4883 ****************************************************************************/
4885 void reply_unlock(struct smb_request *req)
4887 connection_struct *conn = req->conn;
4888 uint64_t count,offset;
4892 START_PROFILE(SMBunlock);
4895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4896 END_PROFILE(SMBunlock);
4900 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4902 if (!check_fsp(conn, req, fsp)) {
4903 END_PROFILE(SMBunlock);
4907 count = (uint64_t)IVAL(req->vwv+1, 0);
4908 offset = (uint64_t)IVAL(req->vwv+3, 0);
4910 status = do_unlock(req->sconn->msg_ctx,
4912 (uint64_t)req->smbpid,
4917 if (NT_STATUS_V(status)) {
4918 reply_nterror(req, status);
4919 END_PROFILE(SMBunlock);
4923 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4924 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4926 reply_outbuf(req, 0, 0);
4928 END_PROFILE(SMBunlock);
4933 #define DBGC_CLASS DBGC_ALL
4935 /****************************************************************************
4937 conn POINTER CAN BE NULL HERE !
4938 ****************************************************************************/
4940 void reply_tdis(struct smb_request *req)
4942 connection_struct *conn = req->conn;
4943 START_PROFILE(SMBtdis);
4946 DEBUG(4,("Invalid connection in tdis\n"));
4947 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
4948 END_PROFILE(SMBtdis);
4954 close_cnum(conn,req->vuid);
4957 reply_outbuf(req, 0, 0);
4958 END_PROFILE(SMBtdis);
4962 /****************************************************************************
4964 conn POINTER CAN BE NULL HERE !
4965 ****************************************************************************/
4967 void reply_echo(struct smb_request *req)
4969 connection_struct *conn = req->conn;
4970 struct smb_perfcount_data local_pcd;
4971 struct smb_perfcount_data *cur_pcd;
4975 START_PROFILE(SMBecho);
4977 smb_init_perfcount_data(&local_pcd);
4980 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4981 END_PROFILE(SMBecho);
4985 smb_reverb = SVAL(req->vwv+0, 0);
4987 reply_outbuf(req, 1, req->buflen);
4989 /* copy any incoming data back out */
4990 if (req->buflen > 0) {
4991 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4994 if (smb_reverb > 100) {
4995 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4999 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5001 /* this makes sure we catch the request pcd */
5002 if (seq_num == smb_reverb) {
5003 cur_pcd = &req->pcd;
5005 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5006 cur_pcd = &local_pcd;
5009 SSVAL(req->outbuf,smb_vwv0,seq_num);
5011 show_msg((char *)req->outbuf);
5012 if (!srv_send_smb(smbd_server_fd(),
5013 (char *)req->outbuf,
5014 true, req->seqnum+1,
5015 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5017 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5020 DEBUG(3,("echo %d times\n", smb_reverb));
5022 TALLOC_FREE(req->outbuf);
5024 END_PROFILE(SMBecho);
5028 /****************************************************************************
5029 Reply to a printopen.
5030 ****************************************************************************/
5032 void reply_printopen(struct smb_request *req)
5034 connection_struct *conn = req->conn;
5038 START_PROFILE(SMBsplopen);
5041 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5042 END_PROFILE(SMBsplopen);
5046 if (!CAN_PRINT(conn)) {
5047 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5048 END_PROFILE(SMBsplopen);
5052 status = file_new(req, conn, &fsp);
5053 if(!NT_STATUS_IS_OK(status)) {
5054 reply_nterror(req, status);
5055 END_PROFILE(SMBsplopen);
5059 /* Open for exclusive use, write only. */
5060 status = print_spool_open(fsp, NULL, req->vuid);
5062 if (!NT_STATUS_IS_OK(status)) {
5063 file_free(req, fsp);
5064 reply_nterror(req, status);
5065 END_PROFILE(SMBsplopen);
5069 reply_outbuf(req, 1, 0);
5070 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5072 DEBUG(3,("openprint fd=%d fnum=%d\n",
5073 fsp->fh->fd, fsp->fnum));
5075 END_PROFILE(SMBsplopen);
5079 /****************************************************************************
5080 Reply to a printclose.
5081 ****************************************************************************/
5083 void reply_printclose(struct smb_request *req)
5085 connection_struct *conn = req->conn;
5089 START_PROFILE(SMBsplclose);
5092 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5093 END_PROFILE(SMBsplclose);
5097 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5099 if (!check_fsp(conn, req, fsp)) {
5100 END_PROFILE(SMBsplclose);
5104 if (!CAN_PRINT(conn)) {
5105 reply_force_doserror(req, ERRSRV, ERRerror);
5106 END_PROFILE(SMBsplclose);
5110 DEBUG(3,("printclose fd=%d fnum=%d\n",
5111 fsp->fh->fd,fsp->fnum));
5113 status = close_file(req, fsp, NORMAL_CLOSE);
5115 if(!NT_STATUS_IS_OK(status)) {
5116 reply_nterror(req, status);
5117 END_PROFILE(SMBsplclose);
5121 reply_outbuf(req, 0, 0);
5123 END_PROFILE(SMBsplclose);
5127 /****************************************************************************
5128 Reply to a printqueue.
5129 ****************************************************************************/
5131 void reply_printqueue(struct smb_request *req)
5133 connection_struct *conn = req->conn;
5137 START_PROFILE(SMBsplretq);
5140 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5141 END_PROFILE(SMBsplretq);
5145 max_count = SVAL(req->vwv+0, 0);
5146 start_index = SVAL(req->vwv+1, 0);
5148 /* we used to allow the client to get the cnum wrong, but that
5149 is really quite gross and only worked when there was only
5150 one printer - I think we should now only accept it if they
5151 get it right (tridge) */
5152 if (!CAN_PRINT(conn)) {
5153 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5154 END_PROFILE(SMBsplretq);
5158 reply_outbuf(req, 2, 3);
5159 SSVAL(req->outbuf,smb_vwv0,0);
5160 SSVAL(req->outbuf,smb_vwv1,0);
5161 SCVAL(smb_buf(req->outbuf),0,1);
5162 SSVAL(smb_buf(req->outbuf),1,0);
5164 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5165 start_index, max_count));
5168 TALLOC_CTX *mem_ctx = talloc_tos();
5171 const char *sharename = lp_servicename(SNUM(conn));
5172 struct rpc_pipe_client *cli = NULL;
5173 struct policy_handle handle;
5174 struct spoolss_DevmodeContainer devmode_ctr;
5175 union spoolss_JobInfo *info;
5177 uint32_t num_to_get;
5181 ZERO_STRUCT(handle);
5183 status = rpc_connect_spoolss_pipe(conn, &cli);
5184 if (!NT_STATUS_IS_OK(status)) {
5185 DEBUG(0, ("reply_printqueue: "
5186 "could not connect to spoolss: %s\n",
5187 nt_errstr(status)));
5188 reply_nterror(req, status);
5192 ZERO_STRUCT(devmode_ctr);
5194 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
5197 SEC_FLAG_MAXIMUM_ALLOWED,
5200 if (!NT_STATUS_IS_OK(status)) {
5201 reply_nterror(req, status);
5204 if (!W_ERROR_IS_OK(werr)) {
5205 reply_nterror(req, werror_to_ntstatus(werr));
5209 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5217 if (!W_ERROR_IS_OK(werr)) {
5218 reply_nterror(req, werror_to_ntstatus(werr));
5222 if (max_count > 0) {
5223 first = start_index;
5225 first = start_index + max_count + 1;
5228 if (first >= count) {
5231 num_to_get = first + MIN(ABS(max_count), count - first);
5234 for (i = first; i < num_to_get; i++) {
5237 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5239 uint16_t qrapjobid = pjobid_to_rap(sharename,
5240 info[i].info2.job_id);
5242 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5248 srv_put_dos_date2(p, 0, qtime);
5249 SCVAL(p, 4, qstatus);
5250 SSVAL(p, 5, qrapjobid);
5251 SIVAL(p, 7, info[i].info2.size);
5253 srvstr_push(blob, req->flags2, p+12,
5254 info[i].info2.notify_name, 16, STR_ASCII);
5256 if (message_push_blob(
5259 blob, sizeof(blob))) == -1) {
5260 reply_nterror(req, NT_STATUS_NO_MEMORY);
5266 SSVAL(req->outbuf,smb_vwv0,count);
5267 SSVAL(req->outbuf,smb_vwv1,
5268 (max_count>0?first+count:first-1));
5269 SCVAL(smb_buf(req->outbuf),0,1);
5270 SSVAL(smb_buf(req->outbuf),1,28*count);
5274 DEBUG(3, ("%u entries returned in queue\n",
5278 if (cli && is_valid_policy_hnd(&handle)) {
5279 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
5284 END_PROFILE(SMBsplretq);
5288 /****************************************************************************
5289 Reply to a printwrite.
5290 ****************************************************************************/
5292 void reply_printwrite(struct smb_request *req)
5294 connection_struct *conn = req->conn;
5299 START_PROFILE(SMBsplwr);
5302 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5303 END_PROFILE(SMBsplwr);
5307 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5309 if (!check_fsp(conn, req, fsp)) {
5310 END_PROFILE(SMBsplwr);
5314 if (!fsp->print_file) {
5315 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5316 END_PROFILE(SMBsplwr);
5320 if (!CHECK_WRITE(fsp)) {
5321 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5322 END_PROFILE(SMBsplwr);
5326 numtowrite = SVAL(req->buf, 1);
5328 if (req->buflen < numtowrite + 3) {
5329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5330 END_PROFILE(SMBsplwr);
5334 data = (const char *)req->buf + 3;
5336 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5337 reply_nterror(req, map_nt_error_from_unix(errno));
5338 END_PROFILE(SMBsplwr);
5342 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5344 END_PROFILE(SMBsplwr);
5348 /****************************************************************************
5350 ****************************************************************************/
5352 void reply_mkdir(struct smb_request *req)
5354 connection_struct *conn = req->conn;
5355 struct smb_filename *smb_dname = NULL;
5356 char *directory = NULL;
5358 TALLOC_CTX *ctx = talloc_tos();
5360 START_PROFILE(SMBmkdir);
5362 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5363 STR_TERMINATE, &status);
5364 if (!NT_STATUS_IS_OK(status)) {
5365 reply_nterror(req, status);
5369 status = filename_convert(ctx, conn,
5370 req->flags2 & FLAGS2_DFS_PATHNAMES,
5375 if (!NT_STATUS_IS_OK(status)) {
5376 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5377 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5378 ERRSRV, ERRbadpath);
5381 reply_nterror(req, status);
5385 status = create_directory(conn, req, smb_dname);
5387 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5389 if (!NT_STATUS_IS_OK(status)) {
5391 if (!use_nt_status()
5392 && NT_STATUS_EQUAL(status,
5393 NT_STATUS_OBJECT_NAME_COLLISION)) {
5395 * Yes, in the DOS error code case we get a
5396 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5397 * samba4 torture test.
5399 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5402 reply_nterror(req, status);
5406 reply_outbuf(req, 0, 0);
5408 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5410 TALLOC_FREE(smb_dname);
5411 END_PROFILE(SMBmkdir);
5415 /****************************************************************************
5417 ****************************************************************************/
5419 void reply_rmdir(struct smb_request *req)
5421 connection_struct *conn = req->conn;
5422 struct smb_filename *smb_dname = NULL;
5423 char *directory = NULL;
5425 TALLOC_CTX *ctx = talloc_tos();
5426 files_struct *fsp = NULL;
5428 struct smbd_server_connection *sconn = req->sconn;
5430 START_PROFILE(SMBrmdir);
5432 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5433 STR_TERMINATE, &status);
5434 if (!NT_STATUS_IS_OK(status)) {
5435 reply_nterror(req, status);
5439 status = filename_convert(ctx, conn,
5440 req->flags2 & FLAGS2_DFS_PATHNAMES,
5445 if (!NT_STATUS_IS_OK(status)) {
5446 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5447 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5448 ERRSRV, ERRbadpath);
5451 reply_nterror(req, status);
5455 if (is_ntfs_stream_smb_fname(smb_dname)) {
5456 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5460 status = SMB_VFS_CREATE_FILE(
5463 0, /* root_dir_fid */
5464 smb_dname, /* fname */
5465 DELETE_ACCESS, /* access_mask */
5466 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5468 FILE_OPEN, /* create_disposition*/
5469 FILE_DIRECTORY_FILE, /* create_options */
5470 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5471 0, /* oplock_request */
5472 0, /* allocation_size */
5473 0, /* private_flags */
5479 if (!NT_STATUS_IS_OK(status)) {
5480 if (open_was_deferred(req->mid)) {
5481 /* We have re-scheduled this call. */
5484 reply_nterror(req, status);
5488 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5489 if (!NT_STATUS_IS_OK(status)) {
5490 close_file(req, fsp, ERROR_CLOSE);
5491 reply_nterror(req, status);
5495 if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
5496 close_file(req, fsp, ERROR_CLOSE);
5497 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5501 status = close_file(req, fsp, NORMAL_CLOSE);
5502 if (!NT_STATUS_IS_OK(status)) {
5503 reply_nterror(req, status);
5505 reply_outbuf(req, 0, 0);
5508 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5510 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5512 TALLOC_FREE(smb_dname);
5513 END_PROFILE(SMBrmdir);
5517 /*******************************************************************
5518 Resolve wildcards in a filename rename.
5519 ********************************************************************/
5521 static bool resolve_wildcards(TALLOC_CTX *ctx,
5526 char *name2_copy = NULL;
5531 char *p,*p2, *pname1, *pname2;
5533 name2_copy = talloc_strdup(ctx, name2);
5538 pname1 = strrchr_m(name1,'/');
5539 pname2 = strrchr_m(name2_copy,'/');
5541 if (!pname1 || !pname2) {
5545 /* Truncate the copy of name2 at the last '/' */
5548 /* Now go past the '/' */
5552 root1 = talloc_strdup(ctx, pname1);
5553 root2 = talloc_strdup(ctx, pname2);
5555 if (!root1 || !root2) {
5559 p = strrchr_m(root1,'.');
5562 ext1 = talloc_strdup(ctx, p+1);
5564 ext1 = talloc_strdup(ctx, "");
5566 p = strrchr_m(root2,'.');
5569 ext2 = talloc_strdup(ctx, p+1);
5571 ext2 = talloc_strdup(ctx, "");
5574 if (!ext1 || !ext2) {
5582 /* Hmmm. Should this be mb-aware ? */
5585 } else if (*p2 == '*') {
5587 root2 = talloc_asprintf(ctx, "%s%s",
5606 /* Hmmm. Should this be mb-aware ? */
5609 } else if (*p2 == '*') {
5611 ext2 = talloc_asprintf(ctx, "%s%s",
5627 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5632 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5644 /****************************************************************************
5645 Ensure open files have their names updated. Updated to notify other smbd's
5647 ****************************************************************************/
5649 static void rename_open_files(connection_struct *conn,
5650 struct share_mode_lock *lck,
5651 const struct smb_filename *smb_fname_dst)
5654 bool did_rename = False;
5657 for(fsp = file_find_di_first(lck->id); fsp;
5658 fsp = file_find_di_next(fsp)) {
5659 /* fsp_name is a relative path under the fsp. To change this for other
5660 sharepaths we need to manipulate relative paths. */
5661 /* TODO - create the absolute path and manipulate the newname
5662 relative to the sharepath. */
5663 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5666 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5667 "(file_id %s) from %s -> %s\n", fsp->fnum,
5668 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5669 smb_fname_str_dbg(smb_fname_dst)));
5671 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5672 if (NT_STATUS_IS_OK(status)) {
5678 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5679 "for %s\n", file_id_string_tos(&lck->id),
5680 smb_fname_str_dbg(smb_fname_dst)));
5683 /* Send messages to all smbd's (not ourself) that the name has changed. */
5684 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5689 /****************************************************************************
5690 We need to check if the source path is a parent directory of the destination
5691 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5692 refuse the rename with a sharing violation. Under UNIX the above call can
5693 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5694 probably need to check that the client is a Windows one before disallowing
5695 this as a UNIX client (one with UNIX extensions) can know the source is a
5696 symlink and make this decision intelligently. Found by an excellent bug
5697 report from <AndyLiebman@aol.com>.
5698 ****************************************************************************/
5700 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5701 const struct smb_filename *smb_fname_dst)
5703 const char *psrc = smb_fname_src->base_name;
5704 const char *pdst = smb_fname_dst->base_name;
5707 if (psrc[0] == '.' && psrc[1] == '/') {
5710 if (pdst[0] == '.' && pdst[1] == '/') {
5713 if ((slen = strlen(psrc)) > strlen(pdst)) {
5716 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5720 * Do the notify calls from a rename
5723 static void notify_rename(connection_struct *conn, bool is_dir,
5724 const struct smb_filename *smb_fname_src,
5725 const struct smb_filename *smb_fname_dst)
5727 char *parent_dir_src = NULL;
5728 char *parent_dir_dst = NULL;
5731 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5732 : FILE_NOTIFY_CHANGE_FILE_NAME;
5734 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5735 &parent_dir_src, NULL) ||
5736 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5737 &parent_dir_dst, NULL)) {
5741 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5742 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5743 smb_fname_src->base_name);
5744 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5745 smb_fname_dst->base_name);
5748 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5749 smb_fname_src->base_name);
5750 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5751 smb_fname_dst->base_name);
5754 /* this is a strange one. w2k3 gives an additional event for
5755 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5756 files, but not directories */
5758 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5759 FILE_NOTIFY_CHANGE_ATTRIBUTES
5760 |FILE_NOTIFY_CHANGE_CREATION,
5761 smb_fname_dst->base_name);
5764 TALLOC_FREE(parent_dir_src);
5765 TALLOC_FREE(parent_dir_dst);
5768 /****************************************************************************
5769 Rename an open file - given an fsp.
5770 ****************************************************************************/
5772 NTSTATUS rename_internals_fsp(connection_struct *conn,
5774 const struct smb_filename *smb_fname_dst_in,
5776 bool replace_if_exists)
5778 TALLOC_CTX *ctx = talloc_tos();
5779 struct smb_filename *smb_fname_dst = NULL;
5780 NTSTATUS status = NT_STATUS_OK;
5781 struct share_mode_lock *lck = NULL;
5782 bool dst_exists, old_is_stream, new_is_stream;
5784 status = check_name(conn, smb_fname_dst_in->base_name);
5785 if (!NT_STATUS_IS_OK(status)) {
5789 /* Make a copy of the dst smb_fname structs */
5791 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5792 if (!NT_STATUS_IS_OK(status)) {
5796 /* Ensure the dst smb_fname contains a '/' */
5797 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5799 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5800 smb_fname_dst->base_name);
5802 status = NT_STATUS_NO_MEMORY;
5805 TALLOC_FREE(smb_fname_dst->base_name);
5806 smb_fname_dst->base_name = tmp;
5810 * Check for special case with case preserving and not
5811 * case sensitive. If the old last component differs from the original
5812 * last component only by case, then we should allow
5813 * the rename (user is trying to change the case of the
5816 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5817 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5818 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5820 char *fname_dst_lcomp_base_mod = NULL;
5821 struct smb_filename *smb_fname_orig_lcomp = NULL;
5824 * Get the last component of the destination name. Note that
5825 * we guarantee that destination name contains a '/' character
5828 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5829 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5830 if (!fname_dst_lcomp_base_mod) {
5831 status = NT_STATUS_NO_MEMORY;
5836 * Create an smb_filename struct using the original last
5837 * component of the destination.
5839 status = create_synthetic_smb_fname_split(ctx,
5840 smb_fname_dst->original_lcomp, NULL,
5841 &smb_fname_orig_lcomp);
5842 if (!NT_STATUS_IS_OK(status)) {
5843 TALLOC_FREE(fname_dst_lcomp_base_mod);
5847 /* If the base names only differ by case, use original. */
5848 if(!strcsequal(fname_dst_lcomp_base_mod,
5849 smb_fname_orig_lcomp->base_name)) {
5852 * Replace the modified last component with the
5855 *last_slash = '\0'; /* Truncate at the '/' */
5856 tmp = talloc_asprintf(smb_fname_dst,
5858 smb_fname_dst->base_name,
5859 smb_fname_orig_lcomp->base_name);
5861 status = NT_STATUS_NO_MEMORY;
5862 TALLOC_FREE(fname_dst_lcomp_base_mod);
5863 TALLOC_FREE(smb_fname_orig_lcomp);
5866 TALLOC_FREE(smb_fname_dst->base_name);
5867 smb_fname_dst->base_name = tmp;
5870 /* If the stream_names only differ by case, use original. */
5871 if(!strcsequal(smb_fname_dst->stream_name,
5872 smb_fname_orig_lcomp->stream_name)) {
5874 /* Use the original stream. */
5875 tmp = talloc_strdup(smb_fname_dst,
5876 smb_fname_orig_lcomp->stream_name);
5878 status = NT_STATUS_NO_MEMORY;
5879 TALLOC_FREE(fname_dst_lcomp_base_mod);
5880 TALLOC_FREE(smb_fname_orig_lcomp);
5883 TALLOC_FREE(smb_fname_dst->stream_name);
5884 smb_fname_dst->stream_name = tmp;
5886 TALLOC_FREE(fname_dst_lcomp_base_mod);
5887 TALLOC_FREE(smb_fname_orig_lcomp);
5891 * If the src and dest names are identical - including case,
5892 * don't do the rename, just return success.
5895 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5896 strcsequal(fsp->fsp_name->stream_name,
5897 smb_fname_dst->stream_name)) {
5898 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5899 "- returning success\n",
5900 smb_fname_str_dbg(smb_fname_dst)));
5901 status = NT_STATUS_OK;
5905 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
5906 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5908 /* Return the correct error code if both names aren't streams. */
5909 if (!old_is_stream && new_is_stream) {
5910 status = NT_STATUS_OBJECT_NAME_INVALID;
5914 if (old_is_stream && !new_is_stream) {
5915 status = NT_STATUS_INVALID_PARAMETER;
5919 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
5921 if(!replace_if_exists && dst_exists) {
5922 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
5923 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5924 smb_fname_str_dbg(smb_fname_dst)));
5925 status = NT_STATUS_OBJECT_NAME_COLLISION;
5930 struct file_id fileid = vfs_file_id_from_sbuf(conn,
5931 &smb_fname_dst->st);
5932 files_struct *dst_fsp = file_find_di_first(fileid);
5933 /* The file can be open when renaming a stream */
5934 if (dst_fsp && !new_is_stream) {
5935 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5936 status = NT_STATUS_ACCESS_DENIED;
5941 /* Ensure we have a valid stat struct for the source. */
5942 status = vfs_stat_fsp(fsp);
5943 if (!NT_STATUS_IS_OK(status)) {
5947 status = can_rename(conn, fsp, attrs);
5949 if (!NT_STATUS_IS_OK(status)) {
5950 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
5951 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
5952 smb_fname_str_dbg(smb_fname_dst)));
5953 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5954 status = NT_STATUS_ACCESS_DENIED;
5958 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
5959 status = NT_STATUS_ACCESS_DENIED;
5962 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5966 * We have the file open ourselves, so not being able to get the
5967 * corresponding share mode lock is a fatal error.
5970 SMB_ASSERT(lck != NULL);
5972 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
5973 uint32 create_options = fsp->fh->private_options;
5975 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
5976 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5977 smb_fname_str_dbg(smb_fname_dst)));
5979 if (lp_map_archive(SNUM(conn)) ||
5980 lp_store_dos_attributes(SNUM(conn))) {
5981 /* We must set the archive bit on the newly
5983 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
5984 uint32_t old_dosmode = dos_mode(conn,
5986 file_set_dosmode(conn,
5988 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
5994 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
5997 rename_open_files(conn, lck, smb_fname_dst);
6000 * A rename acts as a new file create w.r.t. allowing an initial delete
6001 * on close, probably because in Windows there is a new handle to the
6002 * new file. If initial delete on close was requested but not
6003 * originally set, we need to set it here. This is probably not 100% correct,
6004 * but will work for the CIFSFS client which in non-posix mode
6005 * depends on these semantics. JRA.
6008 if (create_options & FILE_DELETE_ON_CLOSE) {
6009 status = can_set_delete_on_close(fsp, 0);
6011 if (NT_STATUS_IS_OK(status)) {
6012 /* Note that here we set the *inital* delete on close flag,
6013 * not the regular one. The magic gets handled in close. */
6014 fsp->initial_delete_on_close = True;
6018 status = NT_STATUS_OK;
6024 if (errno == ENOTDIR || errno == EISDIR) {
6025 status = NT_STATUS_OBJECT_NAME_COLLISION;
6027 status = map_nt_error_from_unix(errno);
6030 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6031 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6032 smb_fname_str_dbg(smb_fname_dst)));
6035 TALLOC_FREE(smb_fname_dst);
6040 /****************************************************************************
6041 The guts of the rename command, split out so it may be called by the NT SMB
6043 ****************************************************************************/
6045 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6046 connection_struct *conn,
6047 struct smb_request *req,
6048 struct smb_filename *smb_fname_src,
6049 struct smb_filename *smb_fname_dst,
6051 bool replace_if_exists,
6054 uint32_t access_mask)
6056 char *fname_src_dir = NULL;
6057 char *fname_src_mask = NULL;
6059 NTSTATUS status = NT_STATUS_OK;
6060 struct smb_Dir *dir_hnd = NULL;
6061 const char *dname = NULL;
6062 char *talloced = NULL;
6064 int create_options = 0;
6065 bool posix_pathnames = lp_posix_pathnames();
6068 * Split the old name into directory and last component
6069 * strings. Note that unix_convert may have stripped off a
6070 * leading ./ from both name and newname if the rename is
6071 * at the root of the share. We need to make sure either both
6072 * name and newname contain a / character or neither of them do
6073 * as this is checked in resolve_wildcards().
6076 /* Split up the directory from the filename/mask. */
6077 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6078 &fname_src_dir, &fname_src_mask);
6079 if (!NT_STATUS_IS_OK(status)) {
6080 status = NT_STATUS_NO_MEMORY;
6085 * We should only check the mangled cache
6086 * here if unix_convert failed. This means
6087 * that the path in 'mask' doesn't exist
6088 * on the file system and so we need to look
6089 * for a possible mangle. This patch from
6090 * Tine Smukavec <valentin.smukavec@hermes.si>.
6093 if (!VALID_STAT(smb_fname_src->st) &&
6094 mangle_is_mangled(fname_src_mask, conn->params)) {
6095 char *new_mask = NULL;
6096 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6099 TALLOC_FREE(fname_src_mask);
6100 fname_src_mask = new_mask;
6104 if (!src_has_wild) {
6108 * Only one file needs to be renamed. Append the mask back
6109 * onto the directory.
6111 TALLOC_FREE(smb_fname_src->base_name);
6112 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6116 if (!smb_fname_src->base_name) {
6117 status = NT_STATUS_NO_MEMORY;
6121 /* Ensure dst fname contains a '/' also */
6122 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6124 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6125 smb_fname_dst->base_name);
6127 status = NT_STATUS_NO_MEMORY;
6130 TALLOC_FREE(smb_fname_dst->base_name);
6131 smb_fname_dst->base_name = tmp;
6134 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6135 "case_preserve = %d, short case preserve = %d, "
6136 "directory = %s, newname = %s, "
6137 "last_component_dest = %s\n",
6138 conn->case_sensitive, conn->case_preserve,
6139 conn->short_case_preserve,
6140 smb_fname_str_dbg(smb_fname_src),
6141 smb_fname_str_dbg(smb_fname_dst),
6142 smb_fname_dst->original_lcomp));
6144 /* The dest name still may have wildcards. */
6145 if (dest_has_wild) {
6146 char *fname_dst_mod = NULL;
6147 if (!resolve_wildcards(smb_fname_dst,
6148 smb_fname_src->base_name,
6149 smb_fname_dst->base_name,
6151 DEBUG(6, ("rename_internals: resolve_wildcards "
6153 smb_fname_src->base_name,
6154 smb_fname_dst->base_name));
6155 status = NT_STATUS_NO_MEMORY;
6158 TALLOC_FREE(smb_fname_dst->base_name);
6159 smb_fname_dst->base_name = fname_dst_mod;
6162 ZERO_STRUCT(smb_fname_src->st);
6163 if (posix_pathnames) {
6164 SMB_VFS_LSTAT(conn, smb_fname_src);
6166 SMB_VFS_STAT(conn, smb_fname_src);
6169 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6170 create_options |= FILE_DIRECTORY_FILE;
6173 status = SMB_VFS_CREATE_FILE(
6176 0, /* root_dir_fid */
6177 smb_fname_src, /* fname */
6178 access_mask, /* access_mask */
6179 (FILE_SHARE_READ | /* share_access */
6181 FILE_OPEN, /* create_disposition*/
6182 create_options, /* create_options */
6183 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6184 0, /* oplock_request */
6185 0, /* allocation_size */
6186 0, /* private_flags */
6192 if (!NT_STATUS_IS_OK(status)) {
6193 DEBUG(3, ("Could not open rename source %s: %s\n",
6194 smb_fname_str_dbg(smb_fname_src),
6195 nt_errstr(status)));
6199 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6200 attrs, replace_if_exists);
6202 close_file(req, fsp, NORMAL_CLOSE);
6204 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6205 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6206 smb_fname_str_dbg(smb_fname_dst)));
6212 * Wildcards - process each file that matches.
6214 if (strequal(fname_src_mask, "????????.???")) {
6215 TALLOC_FREE(fname_src_mask);
6216 fname_src_mask = talloc_strdup(ctx, "*");
6217 if (!fname_src_mask) {
6218 status = NT_STATUS_NO_MEMORY;
6223 status = check_name(conn, fname_src_dir);
6224 if (!NT_STATUS_IS_OK(status)) {
6228 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6230 if (dir_hnd == NULL) {
6231 status = map_nt_error_from_unix(errno);
6235 status = NT_STATUS_NO_SUCH_FILE;
6237 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6238 * - gentest fix. JRA
6241 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6243 files_struct *fsp = NULL;
6244 char *destname = NULL;
6245 bool sysdir_entry = False;
6247 /* Quick check for "." and ".." */
6248 if (ISDOT(dname) || ISDOTDOT(dname)) {
6250 sysdir_entry = True;
6252 TALLOC_FREE(talloced);
6257 if (!is_visible_file(conn, fname_src_dir, dname,
6258 &smb_fname_src->st, false)) {
6259 TALLOC_FREE(talloced);
6263 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6264 TALLOC_FREE(talloced);
6269 status = NT_STATUS_OBJECT_NAME_INVALID;
6273 TALLOC_FREE(smb_fname_src->base_name);
6274 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6278 if (!smb_fname_src->base_name) {
6279 status = NT_STATUS_NO_MEMORY;
6283 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6284 smb_fname_dst->base_name,
6286 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6287 smb_fname_src->base_name, destname));
6288 TALLOC_FREE(talloced);
6292 status = NT_STATUS_NO_MEMORY;
6296 TALLOC_FREE(smb_fname_dst->base_name);
6297 smb_fname_dst->base_name = destname;
6299 ZERO_STRUCT(smb_fname_src->st);
6300 if (posix_pathnames) {
6301 SMB_VFS_LSTAT(conn, smb_fname_src);
6303 SMB_VFS_STAT(conn, smb_fname_src);
6308 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6309 create_options |= FILE_DIRECTORY_FILE;
6312 status = SMB_VFS_CREATE_FILE(
6315 0, /* root_dir_fid */
6316 smb_fname_src, /* fname */
6317 access_mask, /* access_mask */
6318 (FILE_SHARE_READ | /* share_access */
6320 FILE_OPEN, /* create_disposition*/
6321 create_options, /* create_options */
6322 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6323 0, /* oplock_request */
6324 0, /* allocation_size */
6325 0, /* private_flags */
6331 if (!NT_STATUS_IS_OK(status)) {
6332 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6333 "returned %s rename %s -> %s\n",
6335 smb_fname_str_dbg(smb_fname_src),
6336 smb_fname_str_dbg(smb_fname_dst)));
6340 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6342 if (!smb_fname_dst->original_lcomp) {
6343 status = NT_STATUS_NO_MEMORY;
6347 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6348 attrs, replace_if_exists);
6350 close_file(req, fsp, NORMAL_CLOSE);
6352 if (!NT_STATUS_IS_OK(status)) {
6353 DEBUG(3, ("rename_internals_fsp returned %s for "
6354 "rename %s -> %s\n", nt_errstr(status),
6355 smb_fname_str_dbg(smb_fname_src),
6356 smb_fname_str_dbg(smb_fname_dst)));
6362 DEBUG(3,("rename_internals: doing rename on %s -> "
6363 "%s\n", smb_fname_str_dbg(smb_fname_src),
6364 smb_fname_str_dbg(smb_fname_src)));
6365 TALLOC_FREE(talloced);
6367 TALLOC_FREE(dir_hnd);
6369 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6370 status = map_nt_error_from_unix(errno);
6374 TALLOC_FREE(talloced);
6375 TALLOC_FREE(fname_src_dir);
6376 TALLOC_FREE(fname_src_mask);
6380 /****************************************************************************
6382 ****************************************************************************/
6384 void reply_mv(struct smb_request *req)
6386 connection_struct *conn = req->conn;
6388 char *newname = NULL;
6392 bool src_has_wcard = False;
6393 bool dest_has_wcard = False;
6394 TALLOC_CTX *ctx = talloc_tos();
6395 struct smb_filename *smb_fname_src = NULL;
6396 struct smb_filename *smb_fname_dst = NULL;
6398 START_PROFILE(SMBmv);
6401 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6405 attrs = SVAL(req->vwv+0, 0);
6407 p = (const char *)req->buf + 1;
6408 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6409 &status, &src_has_wcard);
6410 if (!NT_STATUS_IS_OK(status)) {
6411 reply_nterror(req, status);
6415 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6416 &status, &dest_has_wcard);
6417 if (!NT_STATUS_IS_OK(status)) {
6418 reply_nterror(req, status);
6422 status = filename_convert(ctx,
6424 req->flags2 & FLAGS2_DFS_PATHNAMES,
6426 UCF_COND_ALLOW_WCARD_LCOMP,
6430 if (!NT_STATUS_IS_OK(status)) {
6431 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6432 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6433 ERRSRV, ERRbadpath);
6436 reply_nterror(req, status);
6440 status = filename_convert(ctx,
6442 req->flags2 & FLAGS2_DFS_PATHNAMES,
6444 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6448 if (!NT_STATUS_IS_OK(status)) {
6449 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6450 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6451 ERRSRV, ERRbadpath);
6454 reply_nterror(req, status);
6458 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6459 smb_fname_str_dbg(smb_fname_dst)));
6461 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6462 attrs, False, src_has_wcard, dest_has_wcard,
6464 if (!NT_STATUS_IS_OK(status)) {
6465 if (open_was_deferred(req->mid)) {
6466 /* We have re-scheduled this call. */
6469 reply_nterror(req, status);
6473 reply_outbuf(req, 0, 0);
6475 TALLOC_FREE(smb_fname_src);
6476 TALLOC_FREE(smb_fname_dst);
6481 /*******************************************************************
6482 Copy a file as part of a reply_copy.
6483 ******************************************************************/
6486 * TODO: check error codes on all callers
6489 NTSTATUS copy_file(TALLOC_CTX *ctx,
6490 connection_struct *conn,
6491 struct smb_filename *smb_fname_src,
6492 struct smb_filename *smb_fname_dst,
6495 bool target_is_directory)
6497 struct smb_filename *smb_fname_dst_tmp = NULL;
6499 files_struct *fsp1,*fsp2;
6501 uint32 new_create_disposition;
6505 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6506 if (!NT_STATUS_IS_OK(status)) {
6511 * If the target is a directory, extract the last component from the
6512 * src filename and append it to the dst filename
6514 if (target_is_directory) {
6517 /* dest/target can't be a stream if it's a directory. */
6518 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6520 p = strrchr_m(smb_fname_src->base_name,'/');
6524 p = smb_fname_src->base_name;
6526 smb_fname_dst_tmp->base_name =
6527 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6529 if (!smb_fname_dst_tmp->base_name) {
6530 status = NT_STATUS_NO_MEMORY;
6535 status = vfs_file_exist(conn, smb_fname_src);
6536 if (!NT_STATUS_IS_OK(status)) {
6540 if (!target_is_directory && count) {
6541 new_create_disposition = FILE_OPEN;
6543 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6545 &new_create_disposition,
6548 status = NT_STATUS_INVALID_PARAMETER;
6553 /* Open the src file for reading. */
6554 status = SMB_VFS_CREATE_FILE(
6557 0, /* root_dir_fid */
6558 smb_fname_src, /* fname */
6559 FILE_GENERIC_READ, /* access_mask */
6560 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6561 FILE_OPEN, /* create_disposition*/
6562 0, /* create_options */
6563 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6564 INTERNAL_OPEN_ONLY, /* oplock_request */
6565 0, /* allocation_size */
6566 0, /* private_flags */
6572 if (!NT_STATUS_IS_OK(status)) {
6576 dosattrs = dos_mode(conn, smb_fname_src);
6578 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6579 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6582 /* Open the dst file for writing. */
6583 status = SMB_VFS_CREATE_FILE(
6586 0, /* root_dir_fid */
6587 smb_fname_dst, /* fname */
6588 FILE_GENERIC_WRITE, /* access_mask */
6589 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6590 new_create_disposition, /* create_disposition*/
6591 0, /* create_options */
6592 dosattrs, /* file_attributes */
6593 INTERNAL_OPEN_ONLY, /* oplock_request */
6594 0, /* allocation_size */
6595 0, /* private_flags */
6601 if (!NT_STATUS_IS_OK(status)) {
6602 close_file(NULL, fsp1, ERROR_CLOSE);
6606 if ((ofun&3) == 1) {
6607 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6608 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6610 * Stop the copy from occurring.
6613 smb_fname_src->st.st_ex_size = 0;
6617 /* Do the actual copy. */
6618 if (smb_fname_src->st.st_ex_size) {
6619 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6622 close_file(NULL, fsp1, NORMAL_CLOSE);
6624 /* Ensure the modtime is set correctly on the destination file. */
6625 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6628 * As we are opening fsp1 read-only we only expect
6629 * an error on close on fsp2 if we are out of space.
6630 * Thus we don't look at the error return from the
6633 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6635 if (!NT_STATUS_IS_OK(status)) {
6639 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6640 status = NT_STATUS_DISK_FULL;
6644 status = NT_STATUS_OK;
6647 TALLOC_FREE(smb_fname_dst_tmp);
6651 /****************************************************************************
6652 Reply to a file copy.
6653 ****************************************************************************/
6655 void reply_copy(struct smb_request *req)
6657 connection_struct *conn = req->conn;
6658 struct smb_filename *smb_fname_src = NULL;
6659 struct smb_filename *smb_fname_dst = NULL;
6660 char *fname_src = NULL;
6661 char *fname_dst = NULL;
6662 char *fname_src_mask = NULL;
6663 char *fname_src_dir = NULL;
6666 int error = ERRnoaccess;
6670 bool target_is_directory=False;
6671 bool source_has_wild = False;
6672 bool dest_has_wild = False;
6674 TALLOC_CTX *ctx = talloc_tos();
6676 START_PROFILE(SMBcopy);
6679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6683 tid2 = SVAL(req->vwv+0, 0);
6684 ofun = SVAL(req->vwv+1, 0);
6685 flags = SVAL(req->vwv+2, 0);
6687 p = (const char *)req->buf;
6688 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6689 &status, &source_has_wild);
6690 if (!NT_STATUS_IS_OK(status)) {
6691 reply_nterror(req, status);
6694 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6695 &status, &dest_has_wild);
6696 if (!NT_STATUS_IS_OK(status)) {
6697 reply_nterror(req, status);
6701 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6703 if (tid2 != conn->cnum) {
6704 /* can't currently handle inter share copies XXXX */
6705 DEBUG(3,("Rejecting inter-share copy\n"));
6706 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6710 status = filename_convert(ctx, conn,
6711 req->flags2 & FLAGS2_DFS_PATHNAMES,
6713 UCF_COND_ALLOW_WCARD_LCOMP,
6716 if (!NT_STATUS_IS_OK(status)) {
6717 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6718 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6719 ERRSRV, ERRbadpath);
6722 reply_nterror(req, status);
6726 status = filename_convert(ctx, conn,
6727 req->flags2 & FLAGS2_DFS_PATHNAMES,
6729 UCF_COND_ALLOW_WCARD_LCOMP,
6732 if (!NT_STATUS_IS_OK(status)) {
6733 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6734 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6735 ERRSRV, ERRbadpath);
6738 reply_nterror(req, status);
6742 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6744 if ((flags&1) && target_is_directory) {
6745 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6749 if ((flags&2) && !target_is_directory) {
6750 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6754 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6755 /* wants a tree copy! XXXX */
6756 DEBUG(3,("Rejecting tree copy\n"));
6757 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6761 /* Split up the directory from the filename/mask. */
6762 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6763 &fname_src_dir, &fname_src_mask);
6764 if (!NT_STATUS_IS_OK(status)) {
6765 reply_nterror(req, NT_STATUS_NO_MEMORY);
6770 * We should only check the mangled cache
6771 * here if unix_convert failed. This means
6772 * that the path in 'mask' doesn't exist
6773 * on the file system and so we need to look
6774 * for a possible mangle. This patch from
6775 * Tine Smukavec <valentin.smukavec@hermes.si>.
6777 if (!VALID_STAT(smb_fname_src->st) &&
6778 mangle_is_mangled(fname_src_mask, conn->params)) {
6779 char *new_mask = NULL;
6780 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6781 &new_mask, conn->params);
6783 /* Use demangled name if one was successfully found. */
6785 TALLOC_FREE(fname_src_mask);
6786 fname_src_mask = new_mask;
6790 if (!source_has_wild) {
6793 * Only one file needs to be copied. Append the mask back onto
6796 TALLOC_FREE(smb_fname_src->base_name);
6797 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6801 if (!smb_fname_src->base_name) {
6802 reply_nterror(req, NT_STATUS_NO_MEMORY);
6806 if (dest_has_wild) {
6807 char *fname_dst_mod = NULL;
6808 if (!resolve_wildcards(smb_fname_dst,
6809 smb_fname_src->base_name,
6810 smb_fname_dst->base_name,
6812 reply_nterror(req, NT_STATUS_NO_MEMORY);
6815 TALLOC_FREE(smb_fname_dst->base_name);
6816 smb_fname_dst->base_name = fname_dst_mod;
6819 status = check_name(conn, smb_fname_src->base_name);
6820 if (!NT_STATUS_IS_OK(status)) {
6821 reply_nterror(req, status);
6825 status = check_name(conn, smb_fname_dst->base_name);
6826 if (!NT_STATUS_IS_OK(status)) {
6827 reply_nterror(req, status);
6831 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6832 ofun, count, target_is_directory);
6834 if(!NT_STATUS_IS_OK(status)) {
6835 reply_nterror(req, status);
6841 struct smb_Dir *dir_hnd = NULL;
6842 const char *dname = NULL;
6843 char *talloced = NULL;
6847 * There is a wildcard that requires us to actually read the
6848 * src dir and copy each file matching the mask to the dst.
6849 * Right now streams won't be copied, but this could
6850 * presumably be added with a nested loop for reach dir entry.
6852 SMB_ASSERT(!smb_fname_src->stream_name);
6853 SMB_ASSERT(!smb_fname_dst->stream_name);
6855 smb_fname_src->stream_name = NULL;
6856 smb_fname_dst->stream_name = NULL;
6858 if (strequal(fname_src_mask,"????????.???")) {
6859 TALLOC_FREE(fname_src_mask);
6860 fname_src_mask = talloc_strdup(ctx, "*");
6861 if (!fname_src_mask) {
6862 reply_nterror(req, NT_STATUS_NO_MEMORY);
6867 status = check_name(conn, fname_src_dir);
6868 if (!NT_STATUS_IS_OK(status)) {
6869 reply_nterror(req, status);
6873 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6874 if (dir_hnd == NULL) {
6875 status = map_nt_error_from_unix(errno);
6876 reply_nterror(req, status);
6882 /* Iterate over the src dir copying each entry to the dst. */
6883 while ((dname = ReadDirName(dir_hnd, &offset,
6884 &smb_fname_src->st, &talloced))) {
6885 char *destname = NULL;
6887 if (ISDOT(dname) || ISDOTDOT(dname)) {
6888 TALLOC_FREE(talloced);
6892 if (!is_visible_file(conn, fname_src_dir, dname,
6893 &smb_fname_src->st, false)) {
6894 TALLOC_FREE(talloced);
6898 if(!mask_match(dname, fname_src_mask,
6899 conn->case_sensitive)) {
6900 TALLOC_FREE(talloced);
6904 error = ERRnoaccess;
6906 /* Get the src smb_fname struct setup. */
6907 TALLOC_FREE(smb_fname_src->base_name);
6908 smb_fname_src->base_name =
6909 talloc_asprintf(smb_fname_src, "%s/%s",
6910 fname_src_dir, dname);
6912 if (!smb_fname_src->base_name) {
6913 TALLOC_FREE(dir_hnd);
6914 TALLOC_FREE(talloced);
6915 reply_nterror(req, NT_STATUS_NO_MEMORY);
6919 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6920 smb_fname_dst->base_name,
6922 TALLOC_FREE(talloced);
6926 TALLOC_FREE(dir_hnd);
6927 TALLOC_FREE(talloced);
6928 reply_nterror(req, NT_STATUS_NO_MEMORY);
6932 TALLOC_FREE(smb_fname_dst->base_name);
6933 smb_fname_dst->base_name = destname;
6935 status = check_name(conn, smb_fname_src->base_name);
6936 if (!NT_STATUS_IS_OK(status)) {
6937 TALLOC_FREE(dir_hnd);
6938 TALLOC_FREE(talloced);
6939 reply_nterror(req, status);
6943 status = check_name(conn, smb_fname_dst->base_name);
6944 if (!NT_STATUS_IS_OK(status)) {
6945 TALLOC_FREE(dir_hnd);
6946 TALLOC_FREE(talloced);
6947 reply_nterror(req, status);
6951 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
6952 smb_fname_src->base_name,
6953 smb_fname_dst->base_name));
6955 status = copy_file(ctx, conn, smb_fname_src,
6956 smb_fname_dst, ofun, count,
6957 target_is_directory);
6958 if (NT_STATUS_IS_OK(status)) {
6962 TALLOC_FREE(talloced);
6964 TALLOC_FREE(dir_hnd);
6968 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
6972 reply_outbuf(req, 1, 0);
6973 SSVAL(req->outbuf,smb_vwv0,count);
6975 TALLOC_FREE(smb_fname_src);
6976 TALLOC_FREE(smb_fname_dst);
6977 TALLOC_FREE(fname_src);
6978 TALLOC_FREE(fname_dst);
6979 TALLOC_FREE(fname_src_mask);
6980 TALLOC_FREE(fname_src_dir);
6982 END_PROFILE(SMBcopy);
6987 #define DBGC_CLASS DBGC_LOCKING
6989 /****************************************************************************
6990 Get a lock pid, dealing with large count requests.
6991 ****************************************************************************/
6993 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
6994 bool large_file_format)
6996 if(!large_file_format)
6997 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
6999 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7002 /****************************************************************************
7003 Get a lock count, dealing with large count requests.
7004 ****************************************************************************/
7006 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7007 bool large_file_format)
7011 if(!large_file_format) {
7012 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7015 #if defined(HAVE_LONGLONG)
7016 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7017 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7018 #else /* HAVE_LONGLONG */
7021 * NT4.x seems to be broken in that it sends large file (64 bit)
7022 * lockingX calls even if the CAP_LARGE_FILES was *not*
7023 * negotiated. For boxes without large unsigned ints truncate the
7024 * lock count by dropping the top 32 bits.
7027 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7028 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7029 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7030 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7031 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7034 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7035 #endif /* HAVE_LONGLONG */
7041 #if !defined(HAVE_LONGLONG)
7042 /****************************************************************************
7043 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7044 ****************************************************************************/
7046 static uint32 map_lock_offset(uint32 high, uint32 low)
7050 uint32 highcopy = high;
7053 * Try and find out how many significant bits there are in high.
7056 for(i = 0; highcopy; i++)
7060 * We use 31 bits not 32 here as POSIX
7061 * lock offsets may not be negative.
7064 mask = (~0) << (31 - i);
7067 return 0; /* Fail. */
7073 #endif /* !defined(HAVE_LONGLONG) */
7075 /****************************************************************************
7076 Get a lock offset, dealing with large offset requests.
7077 ****************************************************************************/
7079 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7080 bool large_file_format, bool *err)
7082 uint64_t offset = 0;
7086 if(!large_file_format) {
7087 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7090 #if defined(HAVE_LONGLONG)
7091 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7092 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7093 #else /* HAVE_LONGLONG */
7096 * NT4.x seems to be broken in that it sends large file (64 bit)
7097 * lockingX calls even if the CAP_LARGE_FILES was *not*
7098 * negotiated. For boxes without large unsigned ints mangle the
7099 * lock offset by mapping the top 32 bits onto the lower 32.
7102 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7103 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7104 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7107 if((new_low = map_lock_offset(high, low)) == 0) {
7109 return (uint64_t)-1;
7112 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7113 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7114 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7115 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7118 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7119 #endif /* HAVE_LONGLONG */
7125 NTSTATUS smbd_do_locking(struct smb_request *req,
7129 uint16_t num_ulocks,
7130 struct smbd_lock_element *ulocks,
7132 struct smbd_lock_element *locks,
7135 connection_struct *conn = req->conn;
7137 NTSTATUS status = NT_STATUS_OK;
7141 /* Data now points at the beginning of the list
7142 of smb_unlkrng structs */
7143 for(i = 0; i < (int)num_ulocks; i++) {
7144 struct smbd_lock_element *e = &ulocks[i];
7146 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7147 "pid %u, file %s\n",
7150 (unsigned int)e->smblctx,
7153 if (e->brltype != UNLOCK_LOCK) {
7154 /* this can only happen with SMB2 */
7155 return NT_STATUS_INVALID_PARAMETER;
7158 status = do_unlock(req->sconn->msg_ctx,
7165 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7166 nt_errstr(status)));
7168 if (!NT_STATUS_IS_OK(status)) {
7173 /* Setup the timeout in seconds. */
7175 if (!lp_blocking_locks(SNUM(conn))) {
7179 /* Data now points at the beginning of the list
7180 of smb_lkrng structs */
7182 for(i = 0; i < (int)num_locks; i++) {
7183 struct smbd_lock_element *e = &locks[i];
7185 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7186 "%llu, file %s timeout = %d\n",
7189 (unsigned long long)e->smblctx,
7193 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7194 struct blocking_lock_record *blr = NULL;
7196 if (num_locks > 1) {
7198 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7199 * if the lock vector contains one entry. When given mutliple cancel
7200 * requests in a single PDU we expect the server to return an
7201 * error. Windows servers seem to accept the request but only
7202 * cancel the first lock.
7203 * JRA - Do what Windows does (tm) :-).
7207 /* MS-CIFS (2.2.4.32.1) behavior. */
7208 return NT_STATUS_DOS(ERRDOS,
7209 ERRcancelviolation);
7211 /* Windows behavior. */
7213 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7214 "cancel request\n"));
7220 if (lp_blocking_locks(SNUM(conn))) {
7222 /* Schedule a message to ourselves to
7223 remove the blocking lock record and
7224 return the right error. */
7226 blr = blocking_lock_cancel_smb1(fsp,
7232 NT_STATUS_FILE_LOCK_CONFLICT);
7234 return NT_STATUS_DOS(
7236 ERRcancelviolation);
7239 /* Remove a matching pending lock. */
7240 status = do_lock_cancel(fsp,
7247 bool blocking_lock = timeout ? true : false;
7248 bool defer_lock = false;
7249 struct byte_range_lock *br_lck;
7250 uint64_t block_smblctx;
7252 br_lck = do_lock(req->sconn->msg_ctx,
7264 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7265 /* Windows internal resolution for blocking locks seems
7266 to be about 200ms... Don't wait for less than that. JRA. */
7267 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7268 timeout = lp_lock_spin_time();
7273 /* If a lock sent with timeout of zero would fail, and
7274 * this lock has been requested multiple times,
7275 * according to brl_lock_failed() we convert this
7276 * request to a blocking lock with a timeout of between
7277 * 150 - 300 milliseconds.
7279 * If lp_lock_spin_time() has been set to 0, we skip
7280 * this blocking retry and fail immediately.
7282 * Replacement for do_lock_spin(). JRA. */
7284 if (!req->sconn->using_smb2 &&
7285 br_lck && lp_blocking_locks(SNUM(conn)) &&
7286 lp_lock_spin_time() && !blocking_lock &&
7287 NT_STATUS_EQUAL((status),
7288 NT_STATUS_FILE_LOCK_CONFLICT))
7291 timeout = lp_lock_spin_time();
7294 if (br_lck && defer_lock) {
7296 * A blocking lock was requested. Package up
7297 * this smb into a queued request and push it
7298 * onto the blocking lock queue.
7300 if(push_blocking_lock_request(br_lck,
7311 TALLOC_FREE(br_lck);
7313 return NT_STATUS_OK;
7317 TALLOC_FREE(br_lck);
7320 if (!NT_STATUS_IS_OK(status)) {
7325 /* If any of the above locks failed, then we must unlock
7326 all of the previous locks (X/Open spec). */
7328 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7330 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7331 i = -1; /* we want to skip the for loop */
7335 * Ensure we don't do a remove on the lock that just failed,
7336 * as under POSIX rules, if we have a lock already there, we
7337 * will delete it (and we shouldn't) .....
7339 for(i--; i >= 0; i--) {
7340 struct smbd_lock_element *e = &locks[i];
7342 do_unlock(req->sconn->msg_ctx,
7352 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7353 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7355 return NT_STATUS_OK;
7358 /****************************************************************************
7359 Reply to a lockingX request.
7360 ****************************************************************************/
7362 void reply_lockingX(struct smb_request *req)
7364 connection_struct *conn = req->conn;
7366 unsigned char locktype;
7367 unsigned char oplocklevel;
7372 const uint8_t *data;
7373 bool large_file_format;
7375 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7376 struct smbd_lock_element *ulocks;
7377 struct smbd_lock_element *locks;
7380 START_PROFILE(SMBlockingX);
7383 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7384 END_PROFILE(SMBlockingX);
7388 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7389 locktype = CVAL(req->vwv+3, 0);
7390 oplocklevel = CVAL(req->vwv+3, 1);
7391 num_ulocks = SVAL(req->vwv+6, 0);
7392 num_locks = SVAL(req->vwv+7, 0);
7393 lock_timeout = IVAL(req->vwv+4, 0);
7394 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7396 if (!check_fsp(conn, req, fsp)) {
7397 END_PROFILE(SMBlockingX);
7403 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7404 /* we don't support these - and CANCEL_LOCK makes w2k
7405 and XP reboot so I don't really want to be
7406 compatible! (tridge) */
7407 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7408 END_PROFILE(SMBlockingX);
7412 /* Check if this is an oplock break on a file
7413 we have granted an oplock on.
7415 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7416 /* Client can insist on breaking to none. */
7417 bool break_to_none = (oplocklevel == 0);
7420 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7421 "for fnum = %d\n", (unsigned int)oplocklevel,
7425 * Make sure we have granted an exclusive or batch oplock on
7429 if (fsp->oplock_type == 0) {
7431 /* The Samba4 nbench simulator doesn't understand
7432 the difference between break to level2 and break
7433 to none from level2 - it sends oplock break
7434 replies in both cases. Don't keep logging an error
7435 message here - just ignore it. JRA. */
7437 DEBUG(5,("reply_lockingX: Error : oplock break from "
7438 "client for fnum = %d (oplock=%d) and no "
7439 "oplock granted on this file (%s).\n",
7440 fsp->fnum, fsp->oplock_type,
7443 /* if this is a pure oplock break request then don't
7445 if (num_locks == 0 && num_ulocks == 0) {
7446 END_PROFILE(SMBlockingX);
7449 END_PROFILE(SMBlockingX);
7450 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7455 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7457 result = remove_oplock(fsp);
7459 result = downgrade_oplock(fsp);
7463 DEBUG(0, ("reply_lockingX: error in removing "
7464 "oplock on file %s\n", fsp_str_dbg(fsp)));
7465 /* Hmmm. Is this panic justified? */
7466 smb_panic("internal tdb error");
7469 reply_to_oplock_break_requests(fsp);
7471 /* if this is a pure oplock break request then don't send a
7473 if (num_locks == 0 && num_ulocks == 0) {
7474 /* Sanity check - ensure a pure oplock break is not a
7476 if(CVAL(req->vwv+0, 0) != 0xff)
7477 DEBUG(0,("reply_lockingX: Error : pure oplock "
7478 "break is a chained %d request !\n",
7479 (unsigned int)CVAL(req->vwv+0, 0)));
7480 END_PROFILE(SMBlockingX);
7486 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7487 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7488 END_PROFILE(SMBlockingX);
7492 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7493 if (ulocks == NULL) {
7494 reply_nterror(req, NT_STATUS_NO_MEMORY);
7495 END_PROFILE(SMBlockingX);
7499 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7500 if (locks == NULL) {
7501 reply_nterror(req, NT_STATUS_NO_MEMORY);
7502 END_PROFILE(SMBlockingX);
7506 /* Data now points at the beginning of the list
7507 of smb_unlkrng structs */
7508 for(i = 0; i < (int)num_ulocks; i++) {
7509 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7510 ulocks[i].count = get_lock_count(data, i, large_file_format);
7511 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7512 ulocks[i].brltype = UNLOCK_LOCK;
7515 * There is no error code marked "stupid client bug".... :-).
7518 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7519 END_PROFILE(SMBlockingX);
7524 /* Now do any requested locks */
7525 data += ((large_file_format ? 20 : 10)*num_ulocks);
7527 /* Data now points at the beginning of the list
7528 of smb_lkrng structs */
7530 for(i = 0; i < (int)num_locks; i++) {
7531 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7532 locks[i].count = get_lock_count(data, i, large_file_format);
7533 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7535 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7536 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7537 locks[i].brltype = PENDING_READ_LOCK;
7539 locks[i].brltype = READ_LOCK;
7542 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7543 locks[i].brltype = PENDING_WRITE_LOCK;
7545 locks[i].brltype = WRITE_LOCK;
7550 * There is no error code marked "stupid client bug".... :-).
7553 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7554 END_PROFILE(SMBlockingX);
7559 status = smbd_do_locking(req, fsp,
7560 locktype, lock_timeout,
7564 if (!NT_STATUS_IS_OK(status)) {
7565 END_PROFILE(SMBlockingX);
7566 reply_nterror(req, status);
7570 END_PROFILE(SMBlockingX);
7574 reply_outbuf(req, 2, 0);
7576 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7577 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7579 END_PROFILE(SMBlockingX);
7584 #define DBGC_CLASS DBGC_ALL
7586 /****************************************************************************
7587 Reply to a SMBreadbmpx (read block multiplex) request.
7588 Always reply with an error, if someone has a platform really needs this,
7589 please contact vl@samba.org
7590 ****************************************************************************/
7592 void reply_readbmpx(struct smb_request *req)
7594 START_PROFILE(SMBreadBmpx);
7595 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7596 END_PROFILE(SMBreadBmpx);
7600 /****************************************************************************
7601 Reply to a SMBreadbs (read block multiplex secondary) request.
7602 Always reply with an error, if someone has a platform really needs this,
7603 please contact vl@samba.org
7604 ****************************************************************************/
7606 void reply_readbs(struct smb_request *req)
7608 START_PROFILE(SMBreadBs);
7609 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7610 END_PROFILE(SMBreadBs);
7614 /****************************************************************************
7615 Reply to a SMBsetattrE.
7616 ****************************************************************************/
7618 void reply_setattrE(struct smb_request *req)
7620 connection_struct *conn = req->conn;
7621 struct smb_file_time ft;
7625 START_PROFILE(SMBsetattrE);
7629 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7633 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7635 if(!fsp || (fsp->conn != conn)) {
7636 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7641 * Convert the DOS times into unix times.
7644 ft.atime = convert_time_t_to_timespec(
7645 srv_make_unix_date2(req->vwv+3));
7646 ft.mtime = convert_time_t_to_timespec(
7647 srv_make_unix_date2(req->vwv+5));
7648 ft.create_time = convert_time_t_to_timespec(
7649 srv_make_unix_date2(req->vwv+1));
7651 reply_outbuf(req, 0, 0);
7654 * Patch from Ray Frush <frush@engr.colostate.edu>
7655 * Sometimes times are sent as zero - ignore them.
7658 /* Ensure we have a valid stat struct for the source. */
7659 status = vfs_stat_fsp(fsp);
7660 if (!NT_STATUS_IS_OK(status)) {
7661 reply_nterror(req, status);
7665 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7666 if (!NT_STATUS_IS_OK(status)) {
7667 reply_nterror(req, status);
7671 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7674 (unsigned int)ft.atime.tv_sec,
7675 (unsigned int)ft.mtime.tv_sec,
7676 (unsigned int)ft.create_time.tv_sec
7679 END_PROFILE(SMBsetattrE);
7684 /* Back from the dead for OS/2..... JRA. */
7686 /****************************************************************************
7687 Reply to a SMBwritebmpx (write block multiplex primary) request.
7688 Always reply with an error, if someone has a platform really needs this,
7689 please contact vl@samba.org
7690 ****************************************************************************/
7692 void reply_writebmpx(struct smb_request *req)
7694 START_PROFILE(SMBwriteBmpx);
7695 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7696 END_PROFILE(SMBwriteBmpx);
7700 /****************************************************************************
7701 Reply to a SMBwritebs (write block multiplex secondary) request.
7702 Always reply with an error, if someone has a platform really needs this,
7703 please contact vl@samba.org
7704 ****************************************************************************/
7706 void reply_writebs(struct smb_request *req)
7708 START_PROFILE(SMBwriteBs);
7709 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7710 END_PROFILE(SMBwriteBs);
7714 /****************************************************************************
7715 Reply to a SMBgetattrE.
7716 ****************************************************************************/
7718 void reply_getattrE(struct smb_request *req)
7720 connection_struct *conn = req->conn;
7723 struct timespec create_ts;
7725 START_PROFILE(SMBgetattrE);
7728 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7729 END_PROFILE(SMBgetattrE);
7733 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7735 if(!fsp || (fsp->conn != conn)) {
7736 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7737 END_PROFILE(SMBgetattrE);
7741 /* Do an fstat on this file */
7743 reply_nterror(req, map_nt_error_from_unix(errno));
7744 END_PROFILE(SMBgetattrE);
7748 mode = dos_mode(conn, fsp->fsp_name);
7751 * Convert the times into dos times. Set create
7752 * date to be last modify date as UNIX doesn't save
7756 reply_outbuf(req, 11, 0);
7758 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7759 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7760 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7761 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7762 /* Should we check pending modtime here ? JRA */
7763 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7764 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7767 SIVAL(req->outbuf, smb_vwv6, 0);
7768 SIVAL(req->outbuf, smb_vwv8, 0);
7770 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7771 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7772 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7774 SSVAL(req->outbuf,smb_vwv10, mode);
7776 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7778 END_PROFILE(SMBgetattrE);