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(struct smbd_server_connection *sconn,
394 const char *name, int name_type)
397 char *trim_name_type;
398 const char *retarget_parm;
401 int retarget_type = 0x20;
402 int retarget_port = 139;
403 struct sockaddr_storage retarget_addr;
404 struct sockaddr_in *in_addr;
408 if (get_socket_port(sconn->sock) != 139) {
412 trim_name = talloc_strdup(talloc_tos(), name);
413 if (trim_name == NULL) {
416 trim_char(trim_name, ' ', ' ');
418 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
420 if (trim_name_type == NULL) {
424 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
425 trim_name_type, NULL);
426 if (retarget_parm == NULL) {
427 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
430 if (retarget_parm == NULL) {
434 retarget = talloc_strdup(trim_name, retarget_parm);
435 if (retarget == NULL) {
439 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
441 p = strchr(retarget, ':');
444 retarget_port = atoi(p);
447 p = strchr_m(retarget, '#');
450 sscanf(p, "%x", &retarget_type);
453 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
455 DEBUG(10, ("could not resolve %s\n", retarget));
459 if (retarget_addr.ss_family != AF_INET) {
460 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
464 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
466 _smb_setlen(outbuf, 6);
467 SCVAL(outbuf, 0, 0x84);
468 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
469 *(uint16_t *)(outbuf+8) = htons(retarget_port);
471 if (!srv_send_smb(sconn->sock, (char *)outbuf, false, 0, false,
473 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
479 TALLOC_FREE(trim_name);
483 /****************************************************************************
484 Reply to a (netbios-level) special message.
485 ****************************************************************************/
487 void reply_special(struct smbd_server_connection *sconn, char *inbuf)
489 int msg_type = CVAL(inbuf,0);
490 int msg_flags = CVAL(inbuf,1);
492 char name_type1, name_type2;
495 * We only really use 4 bytes of the outbuf, but for the smb_setlen
496 * calculation & friends (srv_send_smb uses that) we need the full smb
499 char outbuf[smb_size];
503 memset(outbuf, '\0', sizeof(outbuf));
505 smb_setlen(outbuf,0);
508 case 0x81: /* session request */
510 if (sconn->nbt.got_session) {
511 exit_server_cleanly("multiple session request not permitted");
514 SCVAL(outbuf,0,0x82);
516 if (name_len(inbuf+4) > 50 ||
517 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
518 DEBUG(0,("Invalid name length in session request\n"));
521 name_type1 = name_extract(inbuf,4,name1);
522 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
523 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
524 name1, name_type1, name2, name_type2));
526 if (netbios_session_retarget(sconn, name1, name_type1)) {
527 exit_server_cleanly("retargeted client");
530 set_local_machine_name(name1, True);
531 set_remote_machine_name(name2, True);
533 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
534 get_local_machine_name(), get_remote_machine_name(),
537 if (name_type2 == 'R') {
538 /* We are being asked for a pathworks session ---
540 SCVAL(outbuf, 0,0x83);
544 /* only add the client's machine name to the list
545 of possibly valid usernames if we are operating
546 in share mode security */
547 if (lp_security() == SEC_SHARE) {
548 add_session_user(sconn, get_remote_machine_name());
551 reload_services(sconn->msg_ctx, True);
554 sconn->nbt.got_session = true;
557 case 0x89: /* session keepalive request
558 (some old clients produce this?) */
559 SCVAL(outbuf,0,SMBkeepalive);
563 case 0x82: /* positive session response */
564 case 0x83: /* negative session response */
565 case 0x84: /* retarget session response */
566 DEBUG(0,("Unexpected session response\n"));
569 case SMBkeepalive: /* session keepalive */
574 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
575 msg_type, msg_flags));
577 srv_send_smb(sconn->sock, outbuf, false, 0, false, NULL);
581 /****************************************************************************
583 conn POINTER CAN BE NULL HERE !
584 ****************************************************************************/
586 void reply_tcon(struct smb_request *req)
588 connection_struct *conn = req->conn;
590 char *service_buf = NULL;
591 char *password = NULL;
596 DATA_BLOB password_blob;
597 TALLOC_CTX *ctx = talloc_tos();
598 struct smbd_server_connection *sconn = req->sconn;
600 START_PROFILE(SMBtcon);
602 if (req->buflen < 4) {
603 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
604 END_PROFILE(SMBtcon);
608 p = (const char *)req->buf + 1;
609 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
611 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
613 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
616 if (service_buf == NULL || password == NULL || dev == NULL) {
617 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
618 END_PROFILE(SMBtcon);
621 p = strrchr_m(service_buf,'\\');
625 service = service_buf;
628 password_blob = data_blob(password, pwlen+1);
630 conn = make_connection(sconn,service,password_blob,dev,
631 req->vuid,&nt_status);
634 data_blob_clear_free(&password_blob);
637 reply_nterror(req, nt_status);
638 END_PROFILE(SMBtcon);
642 reply_outbuf(req, 2, 0);
643 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
644 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
645 SSVAL(req->outbuf,smb_tid,conn->cnum);
647 DEBUG(3,("tcon service=%s cnum=%d\n",
648 service, conn->cnum));
650 END_PROFILE(SMBtcon);
654 /****************************************************************************
655 Reply to a tcon and X.
656 conn POINTER CAN BE NULL HERE !
657 ****************************************************************************/
659 void reply_tcon_and_X(struct smb_request *req)
661 connection_struct *conn = req->conn;
662 const char *service = NULL;
664 TALLOC_CTX *ctx = talloc_tos();
665 /* what the cleint thinks the device is */
666 char *client_devicetype = NULL;
667 /* what the server tells the client the share represents */
668 const char *server_devicetype;
674 struct smbd_server_connection *sconn = req->sconn;
676 START_PROFILE(SMBtconX);
679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
680 END_PROFILE(SMBtconX);
684 passlen = SVAL(req->vwv+3, 0);
685 tcon_flags = SVAL(req->vwv+2, 0);
687 /* we might have to close an old one */
688 if ((tcon_flags & 0x1) && conn) {
689 close_cnum(conn,req->vuid);
694 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
695 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
696 END_PROFILE(SMBtconX);
700 if (sconn->smb1.negprot.encrypted_passwords) {
701 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
702 if (lp_security() == SEC_SHARE) {
704 * Security = share always has a pad byte
705 * after the password.
707 p = (const char *)req->buf + passlen + 1;
709 p = (const char *)req->buf + passlen;
712 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
713 /* Ensure correct termination */
714 password.data[passlen]=0;
715 p = (const char *)req->buf + passlen + 1;
718 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
721 data_blob_clear_free(&password);
722 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
723 END_PROFILE(SMBtconX);
728 * the service name can be either: \\server\share
729 * or share directly like on the DELL PowerVault 705
732 q = strchr_m(path+2,'\\');
734 data_blob_clear_free(&password);
735 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
736 END_PROFILE(SMBtconX);
744 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
745 &client_devicetype, p,
746 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
748 if (client_devicetype == NULL) {
749 data_blob_clear_free(&password);
750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
751 END_PROFILE(SMBtconX);
755 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
757 conn = make_connection(sconn, service, password, client_devicetype,
758 req->vuid, &nt_status);
761 data_blob_clear_free(&password);
764 reply_nterror(req, nt_status);
765 END_PROFILE(SMBtconX);
770 server_devicetype = "IPC";
771 else if ( IS_PRINT(conn) )
772 server_devicetype = "LPT1:";
774 server_devicetype = "A:";
776 if (get_Protocol() < PROTOCOL_NT1) {
777 reply_outbuf(req, 2, 0);
778 if (message_push_string(&req->outbuf, server_devicetype,
779 STR_TERMINATE|STR_ASCII) == -1) {
780 reply_nterror(req, NT_STATUS_NO_MEMORY);
781 END_PROFILE(SMBtconX);
785 /* NT sets the fstype of IPC$ to the null string */
786 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
788 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
789 /* Return permissions. */
793 reply_outbuf(req, 7, 0);
796 perm1 = FILE_ALL_ACCESS;
797 perm2 = FILE_ALL_ACCESS;
799 perm1 = CAN_WRITE(conn) ?
804 SIVAL(req->outbuf, smb_vwv3, perm1);
805 SIVAL(req->outbuf, smb_vwv5, perm2);
807 reply_outbuf(req, 3, 0);
810 if ((message_push_string(&req->outbuf, server_devicetype,
811 STR_TERMINATE|STR_ASCII) == -1)
812 || (message_push_string(&req->outbuf, fstype,
813 STR_TERMINATE) == -1)) {
814 reply_nterror(req, NT_STATUS_NO_MEMORY);
815 END_PROFILE(SMBtconX);
819 /* what does setting this bit do? It is set by NT4 and
820 may affect the ability to autorun mounted cdroms */
821 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
822 (lp_csc_policy(SNUM(conn)) << 2));
824 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
825 DEBUG(2,("Serving %s as a Dfs root\n",
826 lp_servicename(SNUM(conn)) ));
827 SSVAL(req->outbuf, smb_vwv2,
828 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
833 DEBUG(3,("tconX service=%s \n",
836 /* set the incoming and outgoing tid to the just created one */
837 SSVAL(req->inbuf,smb_tid,conn->cnum);
838 SSVAL(req->outbuf,smb_tid,conn->cnum);
840 END_PROFILE(SMBtconX);
842 req->tid = conn->cnum;
847 /****************************************************************************
848 Reply to an unknown type.
849 ****************************************************************************/
851 void reply_unknown_new(struct smb_request *req, uint8 type)
853 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
854 smb_fn_name(type), type, type));
855 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
859 /****************************************************************************
861 conn POINTER CAN BE NULL HERE !
862 ****************************************************************************/
864 void reply_ioctl(struct smb_request *req)
866 connection_struct *conn = req->conn;
873 START_PROFILE(SMBioctl);
876 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
877 END_PROFILE(SMBioctl);
881 device = SVAL(req->vwv+1, 0);
882 function = SVAL(req->vwv+2, 0);
883 ioctl_code = (device << 16) + function;
885 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
887 switch (ioctl_code) {
888 case IOCTL_QUERY_JOB_INFO:
892 reply_force_doserror(req, ERRSRV, ERRnosupport);
893 END_PROFILE(SMBioctl);
897 reply_outbuf(req, 8, replysize+1);
898 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
899 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
900 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
901 p = smb_buf(req->outbuf);
902 memset(p, '\0', replysize+1); /* valgrind-safe. */
903 p += 1; /* Allow for alignment */
905 switch (ioctl_code) {
906 case IOCTL_QUERY_JOB_INFO:
908 files_struct *fsp = file_fsp(
909 req, SVAL(req->vwv+0, 0));
911 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
912 END_PROFILE(SMBioctl);
916 if (fsp->print_file) {
917 SSVAL(p, 0, fsp->print_file->rap_jobid);
921 srvstr_push((char *)req->outbuf, req->flags2, p+2,
923 STR_TERMINATE|STR_ASCII);
925 srvstr_push((char *)req->outbuf, req->flags2,
926 p+18, lp_servicename(SNUM(conn)),
927 13, STR_TERMINATE|STR_ASCII);
935 END_PROFILE(SMBioctl);
939 /****************************************************************************
940 Strange checkpath NTSTATUS mapping.
941 ****************************************************************************/
943 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
945 /* Strange DOS error code semantics only for checkpath... */
946 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
947 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
948 /* We need to map to ERRbadpath */
949 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
955 /****************************************************************************
956 Reply to a checkpath.
957 ****************************************************************************/
959 void reply_checkpath(struct smb_request *req)
961 connection_struct *conn = req->conn;
962 struct smb_filename *smb_fname = NULL;
965 TALLOC_CTX *ctx = talloc_tos();
967 START_PROFILE(SMBcheckpath);
969 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
970 STR_TERMINATE, &status);
972 if (!NT_STATUS_IS_OK(status)) {
973 status = map_checkpath_error(req->flags2, status);
974 reply_nterror(req, status);
975 END_PROFILE(SMBcheckpath);
979 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
981 status = filename_convert(ctx,
983 req->flags2 & FLAGS2_DFS_PATHNAMES,
989 if (!NT_STATUS_IS_OK(status)) {
990 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
991 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
993 END_PROFILE(SMBcheckpath);
999 if (!VALID_STAT(smb_fname->st) &&
1000 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1001 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1002 smb_fname_str_dbg(smb_fname), strerror(errno)));
1003 status = map_nt_error_from_unix(errno);
1007 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1008 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1009 ERRDOS, ERRbadpath);
1013 reply_outbuf(req, 0, 0);
1016 /* We special case this - as when a Windows machine
1017 is parsing a path is steps through the components
1018 one at a time - if a component fails it expects
1019 ERRbadpath, not ERRbadfile.
1021 status = map_checkpath_error(req->flags2, status);
1022 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1024 * Windows returns different error codes if
1025 * the parent directory is valid but not the
1026 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1027 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1028 * if the path is invalid.
1030 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1031 ERRDOS, ERRbadpath);
1035 reply_nterror(req, status);
1038 TALLOC_FREE(smb_fname);
1039 END_PROFILE(SMBcheckpath);
1043 /****************************************************************************
1045 ****************************************************************************/
1047 void reply_getatr(struct smb_request *req)
1049 connection_struct *conn = req->conn;
1050 struct smb_filename *smb_fname = NULL;
1057 TALLOC_CTX *ctx = talloc_tos();
1058 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1060 START_PROFILE(SMBgetatr);
1062 p = (const char *)req->buf + 1;
1063 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1064 if (!NT_STATUS_IS_OK(status)) {
1065 reply_nterror(req, status);
1069 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1070 under WfWg - weird! */
1071 if (*fname == '\0') {
1072 mode = aHIDDEN | aDIR;
1073 if (!CAN_WRITE(conn)) {
1079 status = filename_convert(ctx,
1081 req->flags2 & FLAGS2_DFS_PATHNAMES,
1086 if (!NT_STATUS_IS_OK(status)) {
1087 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1088 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1089 ERRSRV, ERRbadpath);
1092 reply_nterror(req, status);
1095 if (!VALID_STAT(smb_fname->st) &&
1096 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1097 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1098 smb_fname_str_dbg(smb_fname),
1100 reply_nterror(req, map_nt_error_from_unix(errno));
1104 mode = dos_mode(conn, smb_fname);
1105 size = smb_fname->st.st_ex_size;
1107 if (ask_sharemode) {
1108 struct timespec write_time_ts;
1109 struct file_id fileid;
1111 ZERO_STRUCT(write_time_ts);
1112 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1113 get_file_infos(fileid, NULL, &write_time_ts);
1114 if (!null_timespec(write_time_ts)) {
1115 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1119 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1125 reply_outbuf(req, 10, 0);
1127 SSVAL(req->outbuf,smb_vwv0,mode);
1128 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1129 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1131 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1133 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1135 if (get_Protocol() >= PROTOCOL_NT1) {
1136 SSVAL(req->outbuf, smb_flg2,
1137 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1140 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1141 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1144 TALLOC_FREE(smb_fname);
1146 END_PROFILE(SMBgetatr);
1150 /****************************************************************************
1152 ****************************************************************************/
1154 void reply_setatr(struct smb_request *req)
1156 struct smb_file_time ft;
1157 connection_struct *conn = req->conn;
1158 struct smb_filename *smb_fname = NULL;
1164 TALLOC_CTX *ctx = talloc_tos();
1166 START_PROFILE(SMBsetatr);
1171 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1175 p = (const char *)req->buf + 1;
1176 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1177 if (!NT_STATUS_IS_OK(status)) {
1178 reply_nterror(req, status);
1182 status = filename_convert(ctx,
1184 req->flags2 & FLAGS2_DFS_PATHNAMES,
1189 if (!NT_STATUS_IS_OK(status)) {
1190 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1191 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1192 ERRSRV, ERRbadpath);
1195 reply_nterror(req, status);
1199 if (smb_fname->base_name[0] == '.' &&
1200 smb_fname->base_name[1] == '\0') {
1202 * Not sure here is the right place to catch this
1203 * condition. Might be moved to somewhere else later -- vl
1205 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1209 mode = SVAL(req->vwv+0, 0);
1210 mtime = srv_make_unix_date3(req->vwv+1);
1212 ft.mtime = convert_time_t_to_timespec(mtime);
1213 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1214 if (!NT_STATUS_IS_OK(status)) {
1215 reply_nterror(req, status);
1219 if (mode != FILE_ATTRIBUTE_NORMAL) {
1220 if (VALID_STAT_OF_DIR(smb_fname->st))
1225 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1227 reply_nterror(req, map_nt_error_from_unix(errno));
1232 reply_outbuf(req, 0, 0);
1234 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1237 TALLOC_FREE(smb_fname);
1238 END_PROFILE(SMBsetatr);
1242 /****************************************************************************
1244 ****************************************************************************/
1246 void reply_dskattr(struct smb_request *req)
1248 connection_struct *conn = req->conn;
1249 uint64_t dfree,dsize,bsize;
1250 START_PROFILE(SMBdskattr);
1252 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1253 reply_nterror(req, map_nt_error_from_unix(errno));
1254 END_PROFILE(SMBdskattr);
1258 reply_outbuf(req, 5, 0);
1260 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1261 double total_space, free_space;
1262 /* we need to scale this to a number that DOS6 can handle. We
1263 use floating point so we can handle large drives on systems
1264 that don't have 64 bit integers
1266 we end up displaying a maximum of 2G to DOS systems
1268 total_space = dsize * (double)bsize;
1269 free_space = dfree * (double)bsize;
1271 dsize = (uint64_t)((total_space+63*512) / (64*512));
1272 dfree = (uint64_t)((free_space+63*512) / (64*512));
1274 if (dsize > 0xFFFF) dsize = 0xFFFF;
1275 if (dfree > 0xFFFF) dfree = 0xFFFF;
1277 SSVAL(req->outbuf,smb_vwv0,dsize);
1278 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1279 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1280 SSVAL(req->outbuf,smb_vwv3,dfree);
1282 SSVAL(req->outbuf,smb_vwv0,dsize);
1283 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1284 SSVAL(req->outbuf,smb_vwv2,512);
1285 SSVAL(req->outbuf,smb_vwv3,dfree);
1288 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1290 END_PROFILE(SMBdskattr);
1295 * Utility function to split the filename from the directory.
1297 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1298 char **fname_dir_out,
1299 char **fname_mask_out)
1301 const char *p = NULL;
1302 char *fname_dir = NULL;
1303 char *fname_mask = NULL;
1305 p = strrchr_m(fname_in, '/');
1307 fname_dir = talloc_strdup(ctx, ".");
1308 fname_mask = talloc_strdup(ctx, fname_in);
1310 fname_dir = talloc_strndup(ctx, fname_in,
1311 PTR_DIFF(p, fname_in));
1312 fname_mask = talloc_strdup(ctx, p+1);
1315 if (!fname_dir || !fname_mask) {
1316 TALLOC_FREE(fname_dir);
1317 TALLOC_FREE(fname_mask);
1318 return NT_STATUS_NO_MEMORY;
1321 *fname_dir_out = fname_dir;
1322 *fname_mask_out = fname_mask;
1323 return NT_STATUS_OK;
1326 /****************************************************************************
1328 Can be called from SMBsearch, SMBffirst or SMBfunique.
1329 ****************************************************************************/
1331 void reply_search(struct smb_request *req)
1333 connection_struct *conn = req->conn;
1335 const char *mask = NULL;
1336 char *directory = NULL;
1337 struct smb_filename *smb_fname = NULL;
1341 struct timespec date;
1343 unsigned int numentries = 0;
1344 unsigned int maxentries = 0;
1345 bool finished = False;
1350 bool check_descend = False;
1351 bool expect_close = False;
1353 bool mask_contains_wcard = False;
1354 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1355 TALLOC_CTX *ctx = talloc_tos();
1356 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1357 struct dptr_struct *dirptr = NULL;
1358 struct smbd_server_connection *sconn = req->sconn;
1360 START_PROFILE(SMBsearch);
1363 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1367 if (lp_posix_pathnames()) {
1368 reply_unknown_new(req, req->cmd);
1372 /* If we were called as SMBffirst then we must expect close. */
1373 if(req->cmd == SMBffirst) {
1374 expect_close = True;
1377 reply_outbuf(req, 1, 3);
1378 maxentries = SVAL(req->vwv+0, 0);
1379 dirtype = SVAL(req->vwv+1, 0);
1380 p = (const char *)req->buf + 1;
1381 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1382 &nt_status, &mask_contains_wcard);
1383 if (!NT_STATUS_IS_OK(nt_status)) {
1384 reply_nterror(req, nt_status);
1389 status_len = SVAL(p, 0);
1392 /* dirtype &= ~aDIR; */
1394 if (status_len == 0) {
1395 nt_status = filename_convert(ctx, conn,
1396 req->flags2 & FLAGS2_DFS_PATHNAMES,
1398 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1399 &mask_contains_wcard,
1401 if (!NT_STATUS_IS_OK(nt_status)) {
1402 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1403 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1404 ERRSRV, ERRbadpath);
1407 reply_nterror(req, nt_status);
1411 directory = smb_fname->base_name;
1413 p = strrchr_m(directory,'/');
1414 if ((p != NULL) && (*directory != '/')) {
1416 directory = talloc_strndup(ctx, directory,
1417 PTR_DIFF(p, directory));
1420 directory = talloc_strdup(ctx,".");
1424 reply_nterror(req, NT_STATUS_NO_MEMORY);
1428 memset((char *)status,'\0',21);
1429 SCVAL(status,0,(dirtype & 0x1F));
1431 nt_status = dptr_create(conn,
1437 mask_contains_wcard,
1440 if (!NT_STATUS_IS_OK(nt_status)) {
1441 reply_nterror(req, nt_status);
1444 dptr_num = dptr_dnum(dirptr);
1447 const char *dirpath;
1449 memcpy(status,p,21);
1450 status_dirtype = CVAL(status,0) & 0x1F;
1451 if (status_dirtype != (dirtype & 0x1F)) {
1452 dirtype = status_dirtype;
1455 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1459 dirpath = dptr_path(sconn, dptr_num);
1460 directory = talloc_strdup(ctx, dirpath);
1462 reply_nterror(req, NT_STATUS_NO_MEMORY);
1466 mask = dptr_wcard(sconn, dptr_num);
1471 * For a 'continue' search we have no string. So
1472 * check from the initial saved string.
1474 mask_contains_wcard = ms_has_wild(mask);
1475 dirtype = dptr_attr(sconn, dptr_num);
1478 DEBUG(4,("dptr_num is %d\n",dptr_num));
1480 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1481 dptr_init_search_op(dirptr);
1483 if ((dirtype&0x1F) == aVOLID) {
1484 char buf[DIR_STRUCT_SIZE];
1485 memcpy(buf,status,21);
1486 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1487 0,aVOLID,0,!allow_long_path_components)) {
1488 reply_nterror(req, NT_STATUS_NO_MEMORY);
1491 dptr_fill(sconn, buf+12,dptr_num);
1492 if (dptr_zero(buf+12) && (status_len==0)) {
1497 if (message_push_blob(&req->outbuf,
1498 data_blob_const(buf, sizeof(buf)))
1500 reply_nterror(req, NT_STATUS_NO_MEMORY);
1508 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1511 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1512 directory,lp_dontdescend(SNUM(conn))));
1513 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1514 check_descend = True;
1517 for (i=numentries;(i<maxentries) && !finished;i++) {
1518 finished = !get_dir_entry(ctx,
1529 char buf[DIR_STRUCT_SIZE];
1530 memcpy(buf,status,21);
1531 if (!make_dir_struct(ctx,
1537 convert_timespec_to_time_t(date),
1538 !allow_long_path_components)) {
1539 reply_nterror(req, NT_STATUS_NO_MEMORY);
1542 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1545 if (message_push_blob(&req->outbuf,
1546 data_blob_const(buf, sizeof(buf)))
1548 reply_nterror(req, NT_STATUS_NO_MEMORY);
1558 /* If we were called as SMBffirst with smb_search_id == NULL
1559 and no entries were found then return error and close dirptr
1562 if (numentries == 0) {
1563 dptr_close(sconn, &dptr_num);
1564 } else if(expect_close && status_len == 0) {
1565 /* Close the dptr - we know it's gone */
1566 dptr_close(sconn, &dptr_num);
1569 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1570 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1571 dptr_close(sconn, &dptr_num);
1574 if ((numentries == 0) && !mask_contains_wcard) {
1575 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1579 SSVAL(req->outbuf,smb_vwv0,numentries);
1580 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1581 SCVAL(smb_buf(req->outbuf),0,5);
1582 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1584 /* The replies here are never long name. */
1585 SSVAL(req->outbuf, smb_flg2,
1586 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1587 if (!allow_long_path_components) {
1588 SSVAL(req->outbuf, smb_flg2,
1589 SVAL(req->outbuf, smb_flg2)
1590 & (~FLAGS2_LONG_PATH_COMPONENTS));
1593 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1594 SSVAL(req->outbuf, smb_flg2,
1595 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1597 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1598 smb_fn_name(req->cmd),
1605 TALLOC_FREE(directory);
1606 TALLOC_FREE(smb_fname);
1607 END_PROFILE(SMBsearch);
1611 /****************************************************************************
1612 Reply to a fclose (stop directory search).
1613 ****************************************************************************/
1615 void reply_fclose(struct smb_request *req)
1623 bool path_contains_wcard = False;
1624 TALLOC_CTX *ctx = talloc_tos();
1625 struct smbd_server_connection *sconn = req->sconn;
1627 START_PROFILE(SMBfclose);
1629 if (lp_posix_pathnames()) {
1630 reply_unknown_new(req, req->cmd);
1631 END_PROFILE(SMBfclose);
1635 p = (const char *)req->buf + 1;
1636 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1637 &err, &path_contains_wcard);
1638 if (!NT_STATUS_IS_OK(err)) {
1639 reply_nterror(req, err);
1640 END_PROFILE(SMBfclose);
1644 status_len = SVAL(p,0);
1647 if (status_len == 0) {
1648 reply_force_doserror(req, ERRSRV, ERRsrverror);
1649 END_PROFILE(SMBfclose);
1653 memcpy(status,p,21);
1655 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1656 /* Close the dptr - we know it's gone */
1657 dptr_close(sconn, &dptr_num);
1660 reply_outbuf(req, 1, 0);
1661 SSVAL(req->outbuf,smb_vwv0,0);
1663 DEBUG(3,("search close\n"));
1665 END_PROFILE(SMBfclose);
1669 /****************************************************************************
1671 ****************************************************************************/
1673 void reply_open(struct smb_request *req)
1675 connection_struct *conn = req->conn;
1676 struct smb_filename *smb_fname = NULL;
1688 uint32 create_disposition;
1689 uint32 create_options = 0;
1690 uint32_t private_flags = 0;
1692 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1693 TALLOC_CTX *ctx = talloc_tos();
1695 START_PROFILE(SMBopen);
1698 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1702 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1703 deny_mode = SVAL(req->vwv+0, 0);
1704 dos_attr = SVAL(req->vwv+1, 0);
1706 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1707 STR_TERMINATE, &status);
1708 if (!NT_STATUS_IS_OK(status)) {
1709 reply_nterror(req, status);
1713 status = filename_convert(ctx,
1715 req->flags2 & FLAGS2_DFS_PATHNAMES,
1720 if (!NT_STATUS_IS_OK(status)) {
1721 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1722 reply_botherror(req,
1723 NT_STATUS_PATH_NOT_COVERED,
1724 ERRSRV, ERRbadpath);
1727 reply_nterror(req, status);
1731 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1732 OPENX_FILE_EXISTS_OPEN, &access_mask,
1733 &share_mode, &create_disposition,
1734 &create_options, &private_flags)) {
1735 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1739 status = SMB_VFS_CREATE_FILE(
1742 0, /* root_dir_fid */
1743 smb_fname, /* fname */
1744 access_mask, /* access_mask */
1745 share_mode, /* share_access */
1746 create_disposition, /* create_disposition*/
1747 create_options, /* create_options */
1748 dos_attr, /* file_attributes */
1749 oplock_request, /* oplock_request */
1750 0, /* allocation_size */
1757 if (!NT_STATUS_IS_OK(status)) {
1758 if (open_was_deferred(req->mid)) {
1759 /* We have re-scheduled this call. */
1762 reply_openerror(req, status);
1766 size = smb_fname->st.st_ex_size;
1767 fattr = dos_mode(conn, smb_fname);
1769 /* Deal with other possible opens having a modified
1771 if (ask_sharemode) {
1772 struct timespec write_time_ts;
1774 ZERO_STRUCT(write_time_ts);
1775 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1776 if (!null_timespec(write_time_ts)) {
1777 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1781 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1784 DEBUG(3,("attempt to open a directory %s\n",
1786 close_file(req, fsp, ERROR_CLOSE);
1787 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1788 ERRDOS, ERRnoaccess);
1792 reply_outbuf(req, 7, 0);
1793 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1794 SSVAL(req->outbuf,smb_vwv1,fattr);
1795 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1796 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1798 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1800 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1801 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1803 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1804 SCVAL(req->outbuf,smb_flg,
1805 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1808 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1809 SCVAL(req->outbuf,smb_flg,
1810 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1813 TALLOC_FREE(smb_fname);
1814 END_PROFILE(SMBopen);
1818 /****************************************************************************
1819 Reply to an open and X.
1820 ****************************************************************************/
1822 void reply_open_and_X(struct smb_request *req)
1824 connection_struct *conn = req->conn;
1825 struct smb_filename *smb_fname = NULL;
1830 /* Breakout the oplock request bits so we can set the
1831 reply bits separately. */
1832 int ex_oplock_request;
1833 int core_oplock_request;
1836 int smb_sattr = SVAL(req->vwv+4, 0);
1837 uint32 smb_time = make_unix_date3(req->vwv+6);
1845 uint64_t allocation_size;
1846 ssize_t retval = -1;
1849 uint32 create_disposition;
1850 uint32 create_options = 0;
1851 uint32_t private_flags = 0;
1852 TALLOC_CTX *ctx = talloc_tos();
1854 START_PROFILE(SMBopenX);
1856 if (req->wct < 15) {
1857 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1861 open_flags = SVAL(req->vwv+2, 0);
1862 deny_mode = SVAL(req->vwv+3, 0);
1863 smb_attr = SVAL(req->vwv+5, 0);
1864 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1865 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1866 oplock_request = ex_oplock_request | core_oplock_request;
1867 smb_ofun = SVAL(req->vwv+8, 0);
1868 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1870 /* If it's an IPC, pass off the pipe handler. */
1872 if (lp_nt_pipe_support()) {
1873 reply_open_pipe_and_X(conn, req);
1875 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1880 /* XXXX we need to handle passed times, sattr and flags */
1881 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1882 STR_TERMINATE, &status);
1883 if (!NT_STATUS_IS_OK(status)) {
1884 reply_nterror(req, status);
1888 status = filename_convert(ctx,
1890 req->flags2 & FLAGS2_DFS_PATHNAMES,
1895 if (!NT_STATUS_IS_OK(status)) {
1896 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1897 reply_botherror(req,
1898 NT_STATUS_PATH_NOT_COVERED,
1899 ERRSRV, ERRbadpath);
1902 reply_nterror(req, status);
1906 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1907 &access_mask, &share_mode,
1908 &create_disposition,
1911 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1915 status = SMB_VFS_CREATE_FILE(
1918 0, /* root_dir_fid */
1919 smb_fname, /* fname */
1920 access_mask, /* access_mask */
1921 share_mode, /* share_access */
1922 create_disposition, /* create_disposition*/
1923 create_options, /* create_options */
1924 smb_attr, /* file_attributes */
1925 oplock_request, /* oplock_request */
1926 0, /* allocation_size */
1931 &smb_action); /* pinfo */
1933 if (!NT_STATUS_IS_OK(status)) {
1934 if (open_was_deferred(req->mid)) {
1935 /* We have re-scheduled this call. */
1938 reply_openerror(req, status);
1942 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1943 if the file is truncated or created. */
1944 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1945 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1946 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1947 close_file(req, fsp, ERROR_CLOSE);
1948 reply_nterror(req, NT_STATUS_DISK_FULL);
1951 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1953 close_file(req, fsp, ERROR_CLOSE);
1954 reply_nterror(req, NT_STATUS_DISK_FULL);
1957 smb_fname->st.st_ex_size =
1958 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1961 fattr = dos_mode(conn, smb_fname);
1962 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1964 close_file(req, fsp, ERROR_CLOSE);
1965 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1969 /* If the caller set the extended oplock request bit
1970 and we granted one (by whatever means) - set the
1971 correct bit for extended oplock reply.
1974 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1975 smb_action |= EXTENDED_OPLOCK_GRANTED;
1978 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1979 smb_action |= EXTENDED_OPLOCK_GRANTED;
1982 /* If the caller set the core oplock request bit
1983 and we granted one (by whatever means) - set the
1984 correct bit for core oplock reply.
1987 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1988 reply_outbuf(req, 19, 0);
1990 reply_outbuf(req, 15, 0);
1993 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1994 SCVAL(req->outbuf, smb_flg,
1995 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1998 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1999 SCVAL(req->outbuf, smb_flg,
2000 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2003 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2004 SSVAL(req->outbuf,smb_vwv3,fattr);
2005 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2006 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2008 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2010 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2011 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2012 SSVAL(req->outbuf,smb_vwv11,smb_action);
2014 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2015 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2020 TALLOC_FREE(smb_fname);
2021 END_PROFILE(SMBopenX);
2025 /****************************************************************************
2026 Reply to a SMBulogoffX.
2027 ****************************************************************************/
2029 void reply_ulogoffX(struct smb_request *req)
2031 struct smbd_server_connection *sconn = req->sconn;
2034 START_PROFILE(SMBulogoffX);
2036 vuser = get_valid_user_struct(sconn, req->vuid);
2039 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2043 /* in user level security we are supposed to close any files
2044 open by this user */
2045 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2046 file_close_user(req->vuid);
2049 invalidate_vuid(sconn, req->vuid);
2051 reply_outbuf(req, 2, 0);
2053 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2055 END_PROFILE(SMBulogoffX);
2056 req->vuid = UID_FIELD_INVALID;
2060 /****************************************************************************
2061 Reply to a mknew or a create.
2062 ****************************************************************************/
2064 void reply_mknew(struct smb_request *req)
2066 connection_struct *conn = req->conn;
2067 struct smb_filename *smb_fname = NULL;
2070 struct smb_file_time ft;
2072 int oplock_request = 0;
2074 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2075 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2076 uint32 create_disposition;
2077 uint32 create_options = 0;
2078 TALLOC_CTX *ctx = talloc_tos();
2080 START_PROFILE(SMBcreate);
2084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2088 fattr = SVAL(req->vwv+0, 0);
2089 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2092 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2094 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2095 STR_TERMINATE, &status);
2096 if (!NT_STATUS_IS_OK(status)) {
2097 reply_nterror(req, status);
2101 status = filename_convert(ctx,
2103 req->flags2 & FLAGS2_DFS_PATHNAMES,
2108 if (!NT_STATUS_IS_OK(status)) {
2109 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2110 reply_botherror(req,
2111 NT_STATUS_PATH_NOT_COVERED,
2112 ERRSRV, ERRbadpath);
2115 reply_nterror(req, status);
2119 if (fattr & aVOLID) {
2120 DEBUG(0,("Attempt to create file (%s) with volid set - "
2121 "please report this\n",
2122 smb_fname_str_dbg(smb_fname)));
2125 if(req->cmd == SMBmknew) {
2126 /* We should fail if file exists. */
2127 create_disposition = FILE_CREATE;
2129 /* Create if file doesn't exist, truncate if it does. */
2130 create_disposition = FILE_OVERWRITE_IF;
2133 status = SMB_VFS_CREATE_FILE(
2136 0, /* root_dir_fid */
2137 smb_fname, /* fname */
2138 access_mask, /* access_mask */
2139 share_mode, /* share_access */
2140 create_disposition, /* create_disposition*/
2141 create_options, /* create_options */
2142 fattr, /* file_attributes */
2143 oplock_request, /* oplock_request */
2144 0, /* allocation_size */
2145 0, /* private_flags */
2151 if (!NT_STATUS_IS_OK(status)) {
2152 if (open_was_deferred(req->mid)) {
2153 /* We have re-scheduled this call. */
2156 reply_openerror(req, status);
2160 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2161 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2162 if (!NT_STATUS_IS_OK(status)) {
2163 END_PROFILE(SMBcreate);
2167 reply_outbuf(req, 1, 0);
2168 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2170 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2171 SCVAL(req->outbuf,smb_flg,
2172 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2175 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2176 SCVAL(req->outbuf,smb_flg,
2177 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2180 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2181 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2182 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2183 (unsigned int)fattr));
2186 TALLOC_FREE(smb_fname);
2187 END_PROFILE(SMBcreate);
2191 /****************************************************************************
2192 Reply to a create temporary file.
2193 ****************************************************************************/
2195 void reply_ctemp(struct smb_request *req)
2197 connection_struct *conn = req->conn;
2198 struct smb_filename *smb_fname = NULL;
2206 TALLOC_CTX *ctx = talloc_tos();
2208 START_PROFILE(SMBctemp);
2211 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2215 fattr = SVAL(req->vwv+0, 0);
2216 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2218 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2219 STR_TERMINATE, &status);
2220 if (!NT_STATUS_IS_OK(status)) {
2221 reply_nterror(req, status);
2225 fname = talloc_asprintf(ctx,
2229 fname = talloc_strdup(ctx, "TMXXXXXX");
2233 reply_nterror(req, NT_STATUS_NO_MEMORY);
2237 status = filename_convert(ctx, conn,
2238 req->flags2 & FLAGS2_DFS_PATHNAMES,
2243 if (!NT_STATUS_IS_OK(status)) {
2244 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2245 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2246 ERRSRV, ERRbadpath);
2249 reply_nterror(req, status);
2253 tmpfd = mkstemp(smb_fname->base_name);
2255 reply_nterror(req, map_nt_error_from_unix(errno));
2259 SMB_VFS_STAT(conn, smb_fname);
2261 /* We should fail if file does not exist. */
2262 status = SMB_VFS_CREATE_FILE(
2265 0, /* root_dir_fid */
2266 smb_fname, /* fname */
2267 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2268 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2269 FILE_OPEN, /* create_disposition*/
2270 0, /* create_options */
2271 fattr, /* file_attributes */
2272 oplock_request, /* oplock_request */
2273 0, /* allocation_size */
2274 0, /* private_flags */
2280 /* close fd from mkstemp() */
2283 if (!NT_STATUS_IS_OK(status)) {
2284 if (open_was_deferred(req->mid)) {
2285 /* We have re-scheduled this call. */
2288 reply_openerror(req, status);
2292 reply_outbuf(req, 1, 0);
2293 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2295 /* the returned filename is relative to the directory */
2296 s = strrchr_m(fsp->fsp_name->base_name, '/');
2298 s = fsp->fsp_name->base_name;
2304 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2305 thing in the byte section. JRA */
2306 SSVALS(p, 0, -1); /* what is this? not in spec */
2308 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2310 reply_nterror(req, NT_STATUS_NO_MEMORY);
2314 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2315 SCVAL(req->outbuf, smb_flg,
2316 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2319 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2320 SCVAL(req->outbuf, smb_flg,
2321 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2324 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2325 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2326 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2328 TALLOC_FREE(smb_fname);
2329 END_PROFILE(SMBctemp);
2333 /*******************************************************************
2334 Check if a user is allowed to rename a file.
2335 ********************************************************************/
2337 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2342 if (!CAN_WRITE(conn)) {
2343 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2346 fmode = dos_mode(conn, fsp->fsp_name);
2347 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2348 return NT_STATUS_NO_SUCH_FILE;
2351 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2352 if (fsp->posix_open) {
2353 return NT_STATUS_OK;
2356 /* If no pathnames are open below this
2357 directory, allow the rename. */
2359 if (file_find_subpath(fsp)) {
2360 return NT_STATUS_ACCESS_DENIED;
2362 return NT_STATUS_OK;
2365 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2366 return NT_STATUS_OK;
2369 return NT_STATUS_ACCESS_DENIED;
2372 /*******************************************************************
2373 * unlink a file with all relevant access checks
2374 *******************************************************************/
2376 static NTSTATUS do_unlink(connection_struct *conn,
2377 struct smb_request *req,
2378 struct smb_filename *smb_fname,
2383 uint32 dirtype_orig = dirtype;
2386 bool posix_paths = lp_posix_pathnames();
2388 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2389 smb_fname_str_dbg(smb_fname),
2392 if (!CAN_WRITE(conn)) {
2393 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2397 ret = SMB_VFS_LSTAT(conn, smb_fname);
2399 ret = SMB_VFS_STAT(conn, smb_fname);
2402 return map_nt_error_from_unix(errno);
2405 fattr = dos_mode(conn, smb_fname);
2407 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2408 dirtype = aDIR|aARCH|aRONLY;
2411 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2413 return NT_STATUS_NO_SUCH_FILE;
2416 if (!dir_check_ftype(conn, fattr, dirtype)) {
2418 return NT_STATUS_FILE_IS_A_DIRECTORY;
2420 return NT_STATUS_NO_SUCH_FILE;
2423 if (dirtype_orig & 0x8000) {
2424 /* These will never be set for POSIX. */
2425 return NT_STATUS_NO_SUCH_FILE;
2429 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2430 return NT_STATUS_FILE_IS_A_DIRECTORY;
2433 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2434 return NT_STATUS_NO_SUCH_FILE;
2437 if (dirtype & 0xFF00) {
2438 /* These will never be set for POSIX. */
2439 return NT_STATUS_NO_SUCH_FILE;
2444 return NT_STATUS_NO_SUCH_FILE;
2447 /* Can't delete a directory. */
2449 return NT_STATUS_FILE_IS_A_DIRECTORY;
2454 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2455 return NT_STATUS_OBJECT_NAME_INVALID;
2456 #endif /* JRATEST */
2458 /* On open checks the open itself will check the share mode, so
2459 don't do it here as we'll get it wrong. */
2461 status = SMB_VFS_CREATE_FILE
2464 0, /* root_dir_fid */
2465 smb_fname, /* fname */
2466 DELETE_ACCESS, /* access_mask */
2467 FILE_SHARE_NONE, /* share_access */
2468 FILE_OPEN, /* create_disposition*/
2469 FILE_NON_DIRECTORY_FILE, /* create_options */
2470 /* file_attributes */
2471 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2472 FILE_ATTRIBUTE_NORMAL,
2473 0, /* oplock_request */
2474 0, /* allocation_size */
2475 0, /* private_flags */
2481 if (!NT_STATUS_IS_OK(status)) {
2482 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2483 nt_errstr(status)));
2487 status = can_set_delete_on_close(fsp, fattr);
2488 if (!NT_STATUS_IS_OK(status)) {
2489 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2491 smb_fname_str_dbg(smb_fname),
2492 nt_errstr(status)));
2493 close_file(req, fsp, NORMAL_CLOSE);
2497 /* The set is across all open files on this dev/inode pair. */
2498 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2499 close_file(req, fsp, NORMAL_CLOSE);
2500 return NT_STATUS_ACCESS_DENIED;
2503 return close_file(req, fsp, NORMAL_CLOSE);
2506 /****************************************************************************
2507 The guts of the unlink command, split out so it may be called by the NT SMB
2509 ****************************************************************************/
2511 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2512 uint32 dirtype, struct smb_filename *smb_fname,
2515 char *fname_dir = NULL;
2516 char *fname_mask = NULL;
2518 NTSTATUS status = NT_STATUS_OK;
2519 TALLOC_CTX *ctx = talloc_tos();
2521 /* Split up the directory from the filename/mask. */
2522 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2523 &fname_dir, &fname_mask);
2524 if (!NT_STATUS_IS_OK(status)) {
2529 * We should only check the mangled cache
2530 * here if unix_convert failed. This means
2531 * that the path in 'mask' doesn't exist
2532 * on the file system and so we need to look
2533 * for a possible mangle. This patch from
2534 * Tine Smukavec <valentin.smukavec@hermes.si>.
2537 if (!VALID_STAT(smb_fname->st) &&
2538 mangle_is_mangled(fname_mask, conn->params)) {
2539 char *new_mask = NULL;
2540 mangle_lookup_name_from_8_3(ctx, fname_mask,
2541 &new_mask, conn->params);
2543 TALLOC_FREE(fname_mask);
2544 fname_mask = new_mask;
2551 * Only one file needs to be unlinked. Append the mask back
2552 * onto the directory.
2554 TALLOC_FREE(smb_fname->base_name);
2555 smb_fname->base_name = talloc_asprintf(smb_fname,
2559 if (!smb_fname->base_name) {
2560 status = NT_STATUS_NO_MEMORY;
2564 dirtype = FILE_ATTRIBUTE_NORMAL;
2567 status = check_name(conn, smb_fname->base_name);
2568 if (!NT_STATUS_IS_OK(status)) {
2572 status = do_unlink(conn, req, smb_fname, dirtype);
2573 if (!NT_STATUS_IS_OK(status)) {
2579 struct smb_Dir *dir_hnd = NULL;
2581 const char *dname = NULL;
2582 char *talloced = NULL;
2584 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2585 status = NT_STATUS_OBJECT_NAME_INVALID;
2589 if (strequal(fname_mask,"????????.???")) {
2590 TALLOC_FREE(fname_mask);
2591 fname_mask = talloc_strdup(ctx, "*");
2593 status = NT_STATUS_NO_MEMORY;
2598 status = check_name(conn, fname_dir);
2599 if (!NT_STATUS_IS_OK(status)) {
2603 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2605 if (dir_hnd == NULL) {
2606 status = map_nt_error_from_unix(errno);
2610 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2611 the pattern matches against the long name, otherwise the short name
2612 We don't implement this yet XXXX
2615 status = NT_STATUS_NO_SUCH_FILE;
2617 while ((dname = ReadDirName(dir_hnd, &offset,
2618 &smb_fname->st, &talloced))) {
2619 TALLOC_CTX *frame = talloc_stackframe();
2621 if (!is_visible_file(conn, fname_dir, dname,
2622 &smb_fname->st, true)) {
2624 TALLOC_FREE(talloced);
2628 /* Quick check for "." and ".." */
2629 if (ISDOT(dname) || ISDOTDOT(dname)) {
2631 TALLOC_FREE(talloced);
2635 if(!mask_match(dname, fname_mask,
2636 conn->case_sensitive)) {
2638 TALLOC_FREE(talloced);
2642 TALLOC_FREE(smb_fname->base_name);
2643 smb_fname->base_name =
2644 talloc_asprintf(smb_fname, "%s/%s",
2647 if (!smb_fname->base_name) {
2648 TALLOC_FREE(dir_hnd);
2649 status = NT_STATUS_NO_MEMORY;
2651 TALLOC_FREE(talloced);
2655 status = check_name(conn, smb_fname->base_name);
2656 if (!NT_STATUS_IS_OK(status)) {
2657 TALLOC_FREE(dir_hnd);
2659 TALLOC_FREE(talloced);
2663 status = do_unlink(conn, req, smb_fname, dirtype);
2664 if (!NT_STATUS_IS_OK(status)) {
2666 TALLOC_FREE(talloced);
2671 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2672 smb_fname->base_name));
2675 TALLOC_FREE(talloced);
2677 TALLOC_FREE(dir_hnd);
2680 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2681 status = map_nt_error_from_unix(errno);
2685 TALLOC_FREE(fname_dir);
2686 TALLOC_FREE(fname_mask);
2690 /****************************************************************************
2692 ****************************************************************************/
2694 void reply_unlink(struct smb_request *req)
2696 connection_struct *conn = req->conn;
2698 struct smb_filename *smb_fname = NULL;
2701 bool path_contains_wcard = False;
2702 TALLOC_CTX *ctx = talloc_tos();
2704 START_PROFILE(SMBunlink);
2707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2711 dirtype = SVAL(req->vwv+0, 0);
2713 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2714 STR_TERMINATE, &status,
2715 &path_contains_wcard);
2716 if (!NT_STATUS_IS_OK(status)) {
2717 reply_nterror(req, status);
2721 status = filename_convert(ctx, conn,
2722 req->flags2 & FLAGS2_DFS_PATHNAMES,
2724 UCF_COND_ALLOW_WCARD_LCOMP,
2725 &path_contains_wcard,
2727 if (!NT_STATUS_IS_OK(status)) {
2728 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2729 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2730 ERRSRV, ERRbadpath);
2733 reply_nterror(req, status);
2737 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2739 status = unlink_internals(conn, req, dirtype, smb_fname,
2740 path_contains_wcard);
2741 if (!NT_STATUS_IS_OK(status)) {
2742 if (open_was_deferred(req->mid)) {
2743 /* We have re-scheduled this call. */
2746 reply_nterror(req, status);
2750 reply_outbuf(req, 0, 0);
2752 TALLOC_FREE(smb_fname);
2753 END_PROFILE(SMBunlink);
2757 /****************************************************************************
2759 ****************************************************************************/
2761 static void fail_readraw(void)
2763 const char *errstr = talloc_asprintf(talloc_tos(),
2764 "FAIL ! reply_readbraw: socket write fail (%s)",
2769 exit_server_cleanly(errstr);
2772 /****************************************************************************
2773 Fake (read/write) sendfile. Returns -1 on read or write fail.
2774 ****************************************************************************/
2776 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2780 size_t tosend = nread;
2787 bufsize = MIN(nread, 65536);
2789 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2793 while (tosend > 0) {
2797 if (tosend > bufsize) {
2802 ret = read_file(fsp,buf,startpos,cur_read);
2808 /* If we had a short read, fill with zeros. */
2809 if (ret < cur_read) {
2810 memset(buf + ret, '\0', cur_read - ret);
2813 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2819 startpos += cur_read;
2823 return (ssize_t)nread;
2826 #if defined(WITH_SENDFILE)
2827 /****************************************************************************
2828 Deal with the case of sendfile reading less bytes from the file than
2829 requested. Fill with zeros (all we can do).
2830 ****************************************************************************/
2832 static void sendfile_short_send(files_struct *fsp,
2837 #define SHORT_SEND_BUFSIZE 1024
2838 if (nread < headersize) {
2839 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2840 "header for file %s (%s). Terminating\n",
2841 fsp_str_dbg(fsp), strerror(errno)));
2842 exit_server_cleanly("sendfile_short_send failed");
2845 nread -= headersize;
2847 if (nread < smb_maxcnt) {
2848 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2850 exit_server_cleanly("sendfile_short_send: "
2854 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2855 "with zeros !\n", fsp_str_dbg(fsp)));
2857 while (nread < smb_maxcnt) {
2859 * We asked for the real file size and told sendfile
2860 * to not go beyond the end of the file. But it can
2861 * happen that in between our fstat call and the
2862 * sendfile call the file was truncated. This is very
2863 * bad because we have already announced the larger
2864 * number of bytes to the client.
2866 * The best we can do now is to send 0-bytes, just as
2867 * a read from a hole in a sparse file would do.
2869 * This should happen rarely enough that I don't care
2870 * about efficiency here :-)
2874 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2875 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2877 exit_server_cleanly("sendfile_short_send: "
2878 "write_data failed");
2885 #endif /* defined WITH_SENDFILE */
2887 /****************************************************************************
2888 Return a readbraw error (4 bytes of zero).
2889 ****************************************************************************/
2891 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2897 smbd_lock_socket(sconn);
2898 if (write_data(sconn->sock,header,4) != 4) {
2901 smbd_unlock_socket(sconn);
2904 /****************************************************************************
2905 Use sendfile in readbraw.
2906 ****************************************************************************/
2908 static void send_file_readbraw(connection_struct *conn,
2909 struct smb_request *req,
2915 struct smbd_server_connection *sconn = req->sconn;
2916 char *outbuf = NULL;
2919 #if defined(WITH_SENDFILE)
2921 * We can only use sendfile on a non-chained packet
2922 * but we can use on a non-oplocked file. tridge proved this
2923 * on a train in Germany :-). JRA.
2924 * reply_readbraw has already checked the length.
2927 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2928 (fsp->wcp == NULL) &&
2929 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
2930 ssize_t sendfile_read = -1;
2932 DATA_BLOB header_blob;
2934 _smb_setlen(header,nread);
2935 header_blob = data_blob_const(header, 4);
2937 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
2938 &header_blob, startpos,
2940 if (sendfile_read == -1) {
2941 /* Returning ENOSYS means no data at all was sent.
2942 * Do this as a normal read. */
2943 if (errno == ENOSYS) {
2944 goto normal_readbraw;
2948 * Special hack for broken Linux with no working sendfile. If we
2949 * return EINTR we sent the header but not the rest of the data.
2950 * Fake this up by doing read/write calls.
2952 if (errno == EINTR) {
2953 /* Ensure we don't do this again. */
2954 set_use_sendfile(SNUM(conn), False);
2955 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2957 if (fake_sendfile(fsp, startpos, nread) == -1) {
2958 DEBUG(0,("send_file_readbraw: "
2959 "fake_sendfile failed for "
2963 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2968 DEBUG(0,("send_file_readbraw: sendfile failed for "
2969 "file %s (%s). Terminating\n",
2970 fsp_str_dbg(fsp), strerror(errno)));
2971 exit_server_cleanly("send_file_readbraw sendfile failed");
2972 } else if (sendfile_read == 0) {
2974 * Some sendfile implementations return 0 to indicate
2975 * that there was a short read, but nothing was
2976 * actually written to the socket. In this case,
2977 * fallback to the normal read path so the header gets
2978 * the correct byte count.
2980 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2981 "bytes falling back to the normal read: "
2982 "%s\n", fsp_str_dbg(fsp)));
2983 goto normal_readbraw;
2986 /* Deal with possible short send. */
2987 if (sendfile_read != 4+nread) {
2988 sendfile_short_send(fsp, sendfile_read, 4, nread);
2996 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2998 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2999 (unsigned)(nread+4)));
3000 reply_readbraw_error(sconn);
3005 ret = read_file(fsp,outbuf+4,startpos,nread);
3006 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3015 _smb_setlen(outbuf,ret);
3016 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret)
3019 TALLOC_FREE(outbuf);
3022 /****************************************************************************
3023 Reply to a readbraw (core+ protocol).
3024 ****************************************************************************/
3026 void reply_readbraw(struct smb_request *req)
3028 connection_struct *conn = req->conn;
3029 struct smbd_server_connection *sconn = req->sconn;
3030 ssize_t maxcount,mincount;
3034 struct lock_struct lock;
3037 START_PROFILE(SMBreadbraw);
3039 if (srv_is_signing_active(sconn) ||
3040 is_encrypted_packet(req->inbuf)) {
3041 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3042 "raw reads/writes are disallowed.");
3046 reply_readbraw_error(sconn);
3047 END_PROFILE(SMBreadbraw);
3051 if (sconn->smb1.echo_handler.trusted_fde) {
3052 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3053 "'async smb echo handler = yes'\n"));
3054 reply_readbraw_error(sconn);
3055 END_PROFILE(SMBreadbraw);
3060 * Special check if an oplock break has been issued
3061 * and the readraw request croses on the wire, we must
3062 * return a zero length response here.
3065 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3068 * We have to do a check_fsp by hand here, as
3069 * we must always return 4 zero bytes on error,
3073 if (!fsp || !conn || conn != fsp->conn ||
3074 req->vuid != fsp->vuid ||
3075 fsp->is_directory || fsp->fh->fd == -1) {
3077 * fsp could be NULL here so use the value from the packet. JRA.
3079 DEBUG(3,("reply_readbraw: fnum %d not valid "
3081 (int)SVAL(req->vwv+0, 0)));
3082 reply_readbraw_error(sconn);
3083 END_PROFILE(SMBreadbraw);
3087 /* Do a "by hand" version of CHECK_READ. */
3088 if (!(fsp->can_read ||
3089 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3090 (fsp->access_mask & FILE_EXECUTE)))) {
3091 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3092 (int)SVAL(req->vwv+0, 0)));
3093 reply_readbraw_error(sconn);
3094 END_PROFILE(SMBreadbraw);
3098 flush_write_cache(fsp, READRAW_FLUSH);
3100 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3101 if(req->wct == 10) {
3103 * This is a large offset (64 bit) read.
3105 #ifdef LARGE_SMB_OFF_T
3107 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3109 #else /* !LARGE_SMB_OFF_T */
3112 * Ensure we haven't been sent a >32 bit offset.
3115 if(IVAL(req->vwv+8, 0) != 0) {
3116 DEBUG(0,("reply_readbraw: large offset "
3117 "(%x << 32) used and we don't support "
3118 "64 bit offsets.\n",
3119 (unsigned int)IVAL(req->vwv+8, 0) ));
3120 reply_readbraw_error();
3121 END_PROFILE(SMBreadbraw);
3125 #endif /* LARGE_SMB_OFF_T */
3128 DEBUG(0,("reply_readbraw: negative 64 bit "
3129 "readraw offset (%.0f) !\n",
3130 (double)startpos ));
3131 reply_readbraw_error(sconn);
3132 END_PROFILE(SMBreadbraw);
3137 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3138 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3140 /* ensure we don't overrun the packet size */
3141 maxcount = MIN(65535,maxcount);
3143 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3144 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3147 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3148 reply_readbraw_error(sconn);
3149 END_PROFILE(SMBreadbraw);
3153 if (fsp_stat(fsp) == 0) {
3154 size = fsp->fsp_name->st.st_ex_size;
3157 if (startpos >= size) {
3160 nread = MIN(maxcount,(size - startpos));
3163 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3164 if (nread < mincount)
3168 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3169 "min=%lu nread=%lu\n",
3170 fsp->fnum, (double)startpos,
3171 (unsigned long)maxcount,
3172 (unsigned long)mincount,
3173 (unsigned long)nread ) );
3175 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3177 DEBUG(5,("reply_readbraw finished\n"));
3179 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3181 END_PROFILE(SMBreadbraw);
3186 #define DBGC_CLASS DBGC_LOCKING
3188 /****************************************************************************
3189 Reply to a lockread (core+ protocol).
3190 ****************************************************************************/
3192 void reply_lockread(struct smb_request *req)
3194 connection_struct *conn = req->conn;
3201 struct byte_range_lock *br_lck = NULL;
3203 struct smbd_server_connection *sconn = req->sconn;
3205 START_PROFILE(SMBlockread);
3208 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3209 END_PROFILE(SMBlockread);
3213 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3215 if (!check_fsp(conn, req, fsp)) {
3216 END_PROFILE(SMBlockread);
3220 if (!CHECK_READ(fsp,req)) {
3221 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3222 END_PROFILE(SMBlockread);
3226 numtoread = SVAL(req->vwv+1, 0);
3227 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3229 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3231 reply_outbuf(req, 5, numtoread + 3);
3233 data = smb_buf(req->outbuf) + 3;
3236 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3237 * protocol request that predates the read/write lock concept.
3238 * Thus instead of asking for a read lock here we need to ask
3239 * for a write lock. JRA.
3240 * Note that the requested lock size is unaffected by max_recv.
3243 br_lck = do_lock(req->sconn->msg_ctx,
3245 (uint64_t)req->smbpid,
3246 (uint64_t)numtoread,
3250 False, /* Non-blocking lock. */
3254 TALLOC_FREE(br_lck);
3256 if (NT_STATUS_V(status)) {
3257 reply_nterror(req, status);
3258 END_PROFILE(SMBlockread);
3263 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3266 if (numtoread > sconn->smb1.negprot.max_recv) {
3267 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3268 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3269 (unsigned int)numtoread,
3270 (unsigned int)sconn->smb1.negprot.max_recv));
3271 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3273 nread = read_file(fsp,data,startpos,numtoread);
3276 reply_nterror(req, map_nt_error_from_unix(errno));
3277 END_PROFILE(SMBlockread);
3281 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3283 SSVAL(req->outbuf,smb_vwv0,nread);
3284 SSVAL(req->outbuf,smb_vwv5,nread+3);
3285 p = smb_buf(req->outbuf);
3286 SCVAL(p,0,0); /* pad byte. */
3289 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3290 fsp->fnum, (int)numtoread, (int)nread));
3292 END_PROFILE(SMBlockread);
3297 #define DBGC_CLASS DBGC_ALL
3299 /****************************************************************************
3301 ****************************************************************************/
3303 void reply_read(struct smb_request *req)
3305 connection_struct *conn = req->conn;
3312 struct lock_struct lock;
3313 struct smbd_server_connection *sconn = req->sconn;
3315 START_PROFILE(SMBread);
3318 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3319 END_PROFILE(SMBread);
3323 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3325 if (!check_fsp(conn, req, fsp)) {
3326 END_PROFILE(SMBread);
3330 if (!CHECK_READ(fsp,req)) {
3331 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3332 END_PROFILE(SMBread);
3336 numtoread = SVAL(req->vwv+1, 0);
3337 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3339 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3342 * The requested read size cannot be greater than max_recv. JRA.
3344 if (numtoread > sconn->smb1.negprot.max_recv) {
3345 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3346 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3347 (unsigned int)numtoread,
3348 (unsigned int)sconn->smb1.negprot.max_recv));
3349 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3352 reply_outbuf(req, 5, numtoread+3);
3354 data = smb_buf(req->outbuf) + 3;
3356 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3357 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3360 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3361 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3362 END_PROFILE(SMBread);
3367 nread = read_file(fsp,data,startpos,numtoread);
3370 reply_nterror(req, map_nt_error_from_unix(errno));
3374 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3376 SSVAL(req->outbuf,smb_vwv0,nread);
3377 SSVAL(req->outbuf,smb_vwv5,nread+3);
3378 SCVAL(smb_buf(req->outbuf),0,1);
3379 SSVAL(smb_buf(req->outbuf),1,nread);
3381 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3382 fsp->fnum, (int)numtoread, (int)nread ) );
3385 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3387 END_PROFILE(SMBread);
3391 /****************************************************************************
3393 ****************************************************************************/
3395 static int setup_readX_header(struct smb_request *req, char *outbuf,
3401 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3402 data = smb_buf(outbuf);
3404 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3406 SCVAL(outbuf,smb_vwv0,0xFF);
3407 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3408 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3409 SSVAL(outbuf,smb_vwv6,
3411 + 1 /* the wct field */
3412 + 12 * sizeof(uint16_t) /* vwv */
3413 + 2); /* the buflen field */
3414 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3415 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3416 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3417 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3421 /****************************************************************************
3422 Reply to a read and X - possibly using sendfile.
3423 ****************************************************************************/
3425 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3426 files_struct *fsp, SMB_OFF_T startpos,
3430 struct lock_struct lock;
3431 int saved_errno = 0;
3433 if(fsp_stat(fsp) == -1) {
3434 reply_nterror(req, map_nt_error_from_unix(errno));
3438 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3439 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3442 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3443 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3447 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3448 (startpos > fsp->fsp_name->st.st_ex_size)
3449 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3451 * We already know that we would do a short read, so don't
3452 * try the sendfile() path.
3454 goto nosendfile_read;
3457 #if defined(WITH_SENDFILE)
3459 * We can only use sendfile on a non-chained packet
3460 * but we can use on a non-oplocked file. tridge proved this
3461 * on a train in Germany :-). JRA.
3464 if (!req_is_in_chain(req) &&
3465 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3466 (fsp->wcp == NULL) &&
3467 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3468 uint8 headerbuf[smb_size + 12 * 2];
3472 * Set up the packet header before send. We
3473 * assume here the sendfile will work (get the
3474 * correct amount of data).
3477 header = data_blob_const(headerbuf, sizeof(headerbuf));
3479 construct_reply_common_req(req, (char *)headerbuf);
3480 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3482 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3483 /* Returning ENOSYS means no data at all was sent.
3484 Do this as a normal read. */
3485 if (errno == ENOSYS) {
3490 * Special hack for broken Linux with no working sendfile. If we
3491 * return EINTR we sent the header but not the rest of the data.
3492 * Fake this up by doing read/write calls.
3495 if (errno == EINTR) {
3496 /* Ensure we don't do this again. */
3497 set_use_sendfile(SNUM(conn), False);
3498 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3499 nread = fake_sendfile(fsp, startpos,
3502 DEBUG(0,("send_file_readX: "
3503 "fake_sendfile failed for "
3507 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3509 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3510 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3511 /* No outbuf here means successful sendfile. */
3515 DEBUG(0,("send_file_readX: sendfile failed for file "
3516 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3518 exit_server_cleanly("send_file_readX sendfile failed");
3519 } else if (nread == 0) {
3521 * Some sendfile implementations return 0 to indicate
3522 * that there was a short read, but nothing was
3523 * actually written to the socket. In this case,
3524 * fallback to the normal read path so the header gets
3525 * the correct byte count.
3527 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3528 "falling back to the normal read: %s\n",
3533 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3534 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3536 /* Deal with possible short send. */
3537 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3538 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3540 /* No outbuf here means successful sendfile. */
3541 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3542 SMB_PERFCOUNT_END(&req->pcd);
3550 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3551 uint8 headerbuf[smb_size + 2*12];
3553 construct_reply_common_req(req, (char *)headerbuf);
3554 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3556 /* Send out the header. */
3557 if (write_data(smbd_server_fd(), (char *)headerbuf,
3558 sizeof(headerbuf)) != sizeof(headerbuf)) {
3559 DEBUG(0,("send_file_readX: write_data failed for file "
3560 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3562 exit_server_cleanly("send_file_readX sendfile failed");
3564 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3566 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3567 "file %s (%s).\n", fsp_str_dbg(fsp),
3569 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3576 reply_outbuf(req, 12, smb_maxcnt);
3578 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3579 saved_errno = errno;
3581 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3584 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3588 setup_readX_header(req, (char *)req->outbuf, nread);
3590 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3591 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3597 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3598 TALLOC_FREE(req->outbuf);
3602 /****************************************************************************
3603 Reply to a read and X.
3604 ****************************************************************************/
3606 void reply_read_and_X(struct smb_request *req)
3608 connection_struct *conn = req->conn;
3612 bool big_readX = False;
3614 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3617 START_PROFILE(SMBreadX);
3619 if ((req->wct != 10) && (req->wct != 12)) {
3620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3624 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3625 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3626 smb_maxcnt = SVAL(req->vwv+5, 0);
3628 /* If it's an IPC, pass off the pipe handler. */
3630 reply_pipe_read_and_X(req);
3631 END_PROFILE(SMBreadX);
3635 if (!check_fsp(conn, req, fsp)) {
3636 END_PROFILE(SMBreadX);
3640 if (!CHECK_READ(fsp,req)) {
3641 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3642 END_PROFILE(SMBreadX);
3646 if (global_client_caps & CAP_LARGE_READX) {
3647 size_t upper_size = SVAL(req->vwv+7, 0);
3648 smb_maxcnt |= (upper_size<<16);
3649 if (upper_size > 1) {
3650 /* Can't do this on a chained packet. */
3651 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3652 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3653 END_PROFILE(SMBreadX);
3656 /* We currently don't do this on signed or sealed data. */
3657 if (srv_is_signing_active(req->sconn) ||
3658 is_encrypted_packet(req->inbuf)) {
3659 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3660 END_PROFILE(SMBreadX);
3663 /* Is there room in the reply for this data ? */
3664 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3666 NT_STATUS_INVALID_PARAMETER);
3667 END_PROFILE(SMBreadX);
3674 if (req->wct == 12) {
3675 #ifdef LARGE_SMB_OFF_T
3677 * This is a large offset (64 bit) read.
3679 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3681 #else /* !LARGE_SMB_OFF_T */
3684 * Ensure we haven't been sent a >32 bit offset.
3687 if(IVAL(req->vwv+10, 0) != 0) {
3688 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3689 "used and we don't support 64 bit offsets.\n",
3690 (unsigned int)IVAL(req->vwv+10, 0) ));
3691 END_PROFILE(SMBreadX);
3692 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3696 #endif /* LARGE_SMB_OFF_T */
3701 NTSTATUS status = schedule_aio_read_and_X(conn,
3706 if (NT_STATUS_IS_OK(status)) {
3707 /* Read scheduled - we're done. */
3710 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3711 /* Real error - report to client. */
3712 END_PROFILE(SMBreadX);
3713 reply_nterror(req, status);
3716 /* NT_STATUS_RETRY - fall back to sync read. */
3719 smbd_lock_socket(req->sconn);
3720 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3721 smbd_unlock_socket(req->sconn);
3724 END_PROFILE(SMBreadX);
3728 /****************************************************************************
3729 Error replies to writebraw must have smb_wct == 1. Fix this up.
3730 ****************************************************************************/
3732 void error_to_writebrawerr(struct smb_request *req)
3734 uint8 *old_outbuf = req->outbuf;
3736 reply_outbuf(req, 1, 0);
3738 memcpy(req->outbuf, old_outbuf, smb_size);
3739 TALLOC_FREE(old_outbuf);
3742 /****************************************************************************
3743 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3744 ****************************************************************************/
3746 void reply_writebraw(struct smb_request *req)
3748 connection_struct *conn = req->conn;
3751 ssize_t total_written=0;
3752 size_t numtowrite=0;
3758 struct lock_struct lock;
3761 START_PROFILE(SMBwritebraw);
3764 * If we ever reply with an error, it must have the SMB command
3765 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3768 SCVAL(req->inbuf,smb_com,SMBwritec);
3770 if (srv_is_signing_active(req->sconn)) {
3771 END_PROFILE(SMBwritebraw);
3772 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3773 "raw reads/writes are disallowed.");
3776 if (req->wct < 12) {
3777 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3778 error_to_writebrawerr(req);
3779 END_PROFILE(SMBwritebraw);
3783 if (req->sconn->smb1.echo_handler.trusted_fde) {
3784 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3785 "'async smb echo handler = yes'\n"));
3786 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3787 error_to_writebrawerr(req);
3788 END_PROFILE(SMBwritebraw);
3792 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3793 if (!check_fsp(conn, req, fsp)) {
3794 error_to_writebrawerr(req);
3795 END_PROFILE(SMBwritebraw);
3799 if (!CHECK_WRITE(fsp)) {
3800 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3801 error_to_writebrawerr(req);
3802 END_PROFILE(SMBwritebraw);
3806 tcount = IVAL(req->vwv+1, 0);
3807 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3808 write_through = BITSETW(req->vwv+7,0);
3810 /* We have to deal with slightly different formats depending
3811 on whether we are using the core+ or lanman1.0 protocol */
3813 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3814 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3815 data = smb_buf(req->inbuf);
3817 numtowrite = SVAL(req->vwv+10, 0);
3818 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3821 /* Ensure we don't write bytes past the end of this packet. */
3822 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3823 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3824 error_to_writebrawerr(req);
3825 END_PROFILE(SMBwritebraw);
3829 if (!fsp->print_file) {
3830 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3831 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3834 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3835 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3836 error_to_writebrawerr(req);
3837 END_PROFILE(SMBwritebraw);
3843 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3846 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3847 "wrote=%d sync=%d\n",
3848 fsp->fnum, (double)startpos, (int)numtowrite,
3849 (int)nwritten, (int)write_through));
3851 if (nwritten < (ssize_t)numtowrite) {
3852 reply_nterror(req, NT_STATUS_DISK_FULL);
3853 error_to_writebrawerr(req);
3857 total_written = nwritten;
3859 /* Allocate a buffer of 64k + length. */
3860 buf = TALLOC_ARRAY(NULL, char, 65540);
3862 reply_nterror(req, NT_STATUS_NO_MEMORY);
3863 error_to_writebrawerr(req);
3867 /* Return a SMBwritebraw message to the redirector to tell
3868 * it to send more bytes */
3870 memcpy(buf, req->inbuf, smb_size);
3871 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3872 SCVAL(buf,smb_com,SMBwritebraw);
3873 SSVALS(buf,smb_vwv0,0xFFFF);
3875 if (!srv_send_smb(smbd_server_fd(),
3877 false, 0, /* no signing */
3878 IS_CONN_ENCRYPTED(conn),
3880 exit_server_cleanly("reply_writebraw: srv_send_smb "
3884 /* Now read the raw data into the buffer and write it */
3885 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3887 if (!NT_STATUS_IS_OK(status)) {
3888 exit_server_cleanly("secondary writebraw failed");
3891 /* Set up outbuf to return the correct size */
3892 reply_outbuf(req, 1, 0);
3894 if (numtowrite != 0) {
3896 if (numtowrite > 0xFFFF) {
3897 DEBUG(0,("reply_writebraw: Oversize secondary write "
3898 "raw requested (%u). Terminating\n",
3899 (unsigned int)numtowrite ));
3900 exit_server_cleanly("secondary writebraw failed");
3903 if (tcount > nwritten+numtowrite) {
3904 DEBUG(3,("reply_writebraw: Client overestimated the "
3906 (int)tcount,(int)nwritten,(int)numtowrite));
3909 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3911 if (!NT_STATUS_IS_OK(status)) {
3912 DEBUG(0,("reply_writebraw: Oversize secondary write "
3913 "raw read failed (%s). Terminating\n",
3914 nt_errstr(status)));
3915 exit_server_cleanly("secondary writebraw failed");
3918 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3919 if (nwritten == -1) {
3921 reply_nterror(req, map_nt_error_from_unix(errno));
3922 error_to_writebrawerr(req);
3926 if (nwritten < (ssize_t)numtowrite) {
3927 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3928 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3932 total_written += nwritten;
3937 SSVAL(req->outbuf,smb_vwv0,total_written);
3939 status = sync_file(conn, fsp, write_through);
3940 if (!NT_STATUS_IS_OK(status)) {
3941 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3942 fsp_str_dbg(fsp), nt_errstr(status)));
3943 reply_nterror(req, status);
3944 error_to_writebrawerr(req);
3948 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3950 fsp->fnum, (double)startpos, (int)numtowrite,
3951 (int)total_written));
3953 if (!fsp->print_file) {
3954 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3957 /* We won't return a status if write through is not selected - this
3958 * follows what WfWg does */
3959 END_PROFILE(SMBwritebraw);
3961 if (!write_through && total_written==tcount) {
3963 #if RABBIT_PELLET_FIX
3965 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3966 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3969 if (!send_keepalive(smbd_server_fd())) {
3970 exit_server_cleanly("reply_writebraw: send of "
3971 "keepalive failed");
3974 TALLOC_FREE(req->outbuf);
3979 if (!fsp->print_file) {
3980 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3983 END_PROFILE(SMBwritebraw);
3988 #define DBGC_CLASS DBGC_LOCKING
3990 /****************************************************************************
3991 Reply to a writeunlock (core+).
3992 ****************************************************************************/
3994 void reply_writeunlock(struct smb_request *req)
3996 connection_struct *conn = req->conn;
3997 ssize_t nwritten = -1;
4001 NTSTATUS status = NT_STATUS_OK;
4003 struct lock_struct lock;
4004 int saved_errno = 0;
4006 START_PROFILE(SMBwriteunlock);
4009 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4010 END_PROFILE(SMBwriteunlock);
4014 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4016 if (!check_fsp(conn, req, fsp)) {
4017 END_PROFILE(SMBwriteunlock);
4021 if (!CHECK_WRITE(fsp)) {
4022 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4023 END_PROFILE(SMBwriteunlock);
4027 numtowrite = SVAL(req->vwv+1, 0);
4028 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4029 data = (const char *)req->buf + 3;
4031 if (!fsp->print_file && numtowrite > 0) {
4032 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4033 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4036 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4037 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4038 END_PROFILE(SMBwriteunlock);
4043 /* The special X/Open SMB protocol handling of
4044 zero length writes is *NOT* done for
4046 if(numtowrite == 0) {
4049 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4050 saved_errno = errno;
4053 status = sync_file(conn, fsp, False /* write through */);
4054 if (!NT_STATUS_IS_OK(status)) {
4055 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4056 fsp_str_dbg(fsp), nt_errstr(status)));
4057 reply_nterror(req, status);
4062 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4066 if((nwritten < numtowrite) && (numtowrite != 0)) {
4067 reply_nterror(req, NT_STATUS_DISK_FULL);
4071 if (numtowrite && !fsp->print_file) {
4072 status = do_unlock(req->sconn->msg_ctx,
4074 (uint64_t)req->smbpid,
4075 (uint64_t)numtowrite,
4079 if (NT_STATUS_V(status)) {
4080 reply_nterror(req, status);
4085 reply_outbuf(req, 1, 0);
4087 SSVAL(req->outbuf,smb_vwv0,nwritten);
4089 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4090 fsp->fnum, (int)numtowrite, (int)nwritten));
4093 if (numtowrite && !fsp->print_file) {
4094 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4097 END_PROFILE(SMBwriteunlock);
4102 #define DBGC_CLASS DBGC_ALL
4104 /****************************************************************************
4106 ****************************************************************************/
4108 void reply_write(struct smb_request *req)
4110 connection_struct *conn = req->conn;
4112 ssize_t nwritten = -1;
4116 struct lock_struct lock;
4118 int saved_errno = 0;
4120 START_PROFILE(SMBwrite);
4123 END_PROFILE(SMBwrite);
4124 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4128 /* If it's an IPC, pass off the pipe handler. */
4130 reply_pipe_write(req);
4131 END_PROFILE(SMBwrite);
4135 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4137 if (!check_fsp(conn, req, fsp)) {
4138 END_PROFILE(SMBwrite);
4142 if (!CHECK_WRITE(fsp)) {
4143 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4144 END_PROFILE(SMBwrite);
4148 numtowrite = SVAL(req->vwv+1, 0);
4149 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4150 data = (const char *)req->buf + 3;
4152 if (!fsp->print_file) {
4153 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4154 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4157 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4158 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4159 END_PROFILE(SMBwrite);
4165 * X/Open SMB protocol says that if smb_vwv1 is
4166 * zero then the file size should be extended or
4167 * truncated to the size given in smb_vwv[2-3].
4170 if(numtowrite == 0) {
4172 * This is actually an allocate call, and set EOF. JRA.
4174 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4176 reply_nterror(req, NT_STATUS_DISK_FULL);
4179 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4181 reply_nterror(req, NT_STATUS_DISK_FULL);
4184 trigger_write_time_update_immediate(fsp);
4186 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4189 status = sync_file(conn, fsp, False);
4190 if (!NT_STATUS_IS_OK(status)) {
4191 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4192 fsp_str_dbg(fsp), nt_errstr(status)));
4193 reply_nterror(req, status);
4198 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4202 if((nwritten == 0) && (numtowrite != 0)) {
4203 reply_nterror(req, NT_STATUS_DISK_FULL);
4207 reply_outbuf(req, 1, 0);
4209 SSVAL(req->outbuf,smb_vwv0,nwritten);
4211 if (nwritten < (ssize_t)numtowrite) {
4212 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4213 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4216 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4219 if (!fsp->print_file) {
4220 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4223 END_PROFILE(SMBwrite);
4227 /****************************************************************************
4228 Ensure a buffer is a valid writeX for recvfile purposes.
4229 ****************************************************************************/
4231 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4232 (2*14) + /* word count (including bcc) */ \
4235 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4236 const uint8_t *inbuf)
4239 connection_struct *conn = NULL;
4240 unsigned int doff = 0;
4241 size_t len = smb_len_large(inbuf);
4243 if (is_encrypted_packet(inbuf)) {
4244 /* Can't do this on encrypted
4249 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4253 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4254 CVAL(inbuf,smb_wct) != 14) {
4255 DEBUG(10,("is_valid_writeX_buffer: chained or "
4256 "invalid word length.\n"));
4260 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4262 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4266 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4269 if (IS_PRINT(conn)) {
4270 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4273 doff = SVAL(inbuf,smb_vwv11);
4275 numtowrite = SVAL(inbuf,smb_vwv10);
4277 if (len > doff && len - doff > 0xFFFF) {
4278 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4281 if (numtowrite == 0) {
4282 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4286 /* Ensure the sizes match up. */
4287 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4288 /* no pad byte...old smbclient :-( */
4289 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4291 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4295 if (len - doff != numtowrite) {
4296 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4297 "len = %u, doff = %u, numtowrite = %u\n",
4300 (unsigned int)numtowrite ));
4304 DEBUG(10,("is_valid_writeX_buffer: true "
4305 "len = %u, doff = %u, numtowrite = %u\n",
4308 (unsigned int)numtowrite ));
4313 /****************************************************************************
4314 Reply to a write and X.
4315 ****************************************************************************/
4317 void reply_write_and_X(struct smb_request *req)
4319 connection_struct *conn = req->conn;
4321 struct lock_struct lock;
4326 unsigned int smb_doff;
4327 unsigned int smblen;
4330 int saved_errno = 0;
4332 START_PROFILE(SMBwriteX);
4334 if ((req->wct != 12) && (req->wct != 14)) {
4335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4336 END_PROFILE(SMBwriteX);
4340 numtowrite = SVAL(req->vwv+10, 0);
4341 smb_doff = SVAL(req->vwv+11, 0);
4342 smblen = smb_len(req->inbuf);
4344 if (req->unread_bytes > 0xFFFF ||
4345 (smblen > smb_doff &&
4346 smblen - smb_doff > 0xFFFF)) {
4347 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4350 if (req->unread_bytes) {
4351 /* Can't do a recvfile write on IPC$ */
4353 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4354 END_PROFILE(SMBwriteX);
4357 if (numtowrite != req->unread_bytes) {
4358 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4359 END_PROFILE(SMBwriteX);
4363 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4364 smb_doff + numtowrite > smblen) {
4365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4366 END_PROFILE(SMBwriteX);
4371 /* If it's an IPC, pass off the pipe handler. */
4373 if (req->unread_bytes) {
4374 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4375 END_PROFILE(SMBwriteX);
4378 reply_pipe_write_and_X(req);
4379 END_PROFILE(SMBwriteX);
4383 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4384 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4385 write_through = BITSETW(req->vwv+7,0);
4387 if (!check_fsp(conn, req, fsp)) {
4388 END_PROFILE(SMBwriteX);
4392 if (!CHECK_WRITE(fsp)) {
4393 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4394 END_PROFILE(SMBwriteX);
4398 data = smb_base(req->inbuf) + smb_doff;
4400 if(req->wct == 14) {
4401 #ifdef LARGE_SMB_OFF_T
4403 * This is a large offset (64 bit) write.
4405 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4407 #else /* !LARGE_SMB_OFF_T */
4410 * Ensure we haven't been sent a >32 bit offset.
4413 if(IVAL(req->vwv+12, 0) != 0) {
4414 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4415 "used and we don't support 64 bit offsets.\n",
4416 (unsigned int)IVAL(req->vwv+12, 0) ));
4417 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4418 END_PROFILE(SMBwriteX);
4422 #endif /* LARGE_SMB_OFF_T */
4425 /* X/Open SMB protocol says that, unlike SMBwrite
4426 if the length is zero then NO truncation is
4427 done, just a write of zero. To truncate a file,
4430 if(numtowrite == 0) {
4433 if (req->unread_bytes == 0) {
4434 status = schedule_aio_write_and_X(conn,
4441 if (NT_STATUS_IS_OK(status)) {
4442 /* write scheduled - we're done. */
4445 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4446 /* Real error - report to client. */
4447 reply_nterror(req, status);
4450 /* NT_STATUS_RETRY - fall through to sync write. */
4453 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4454 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4457 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4458 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4462 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4463 saved_errno = errno;
4465 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4469 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4473 if((nwritten == 0) && (numtowrite != 0)) {
4474 reply_nterror(req, NT_STATUS_DISK_FULL);
4478 reply_outbuf(req, 6, 0);
4479 SSVAL(req->outbuf,smb_vwv2,nwritten);
4480 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4482 if (nwritten < (ssize_t)numtowrite) {
4483 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4484 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4487 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4488 fsp->fnum, (int)numtowrite, (int)nwritten));
4490 status = sync_file(conn, fsp, write_through);
4491 if (!NT_STATUS_IS_OK(status)) {
4492 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4493 fsp_str_dbg(fsp), nt_errstr(status)));
4494 reply_nterror(req, status);
4498 END_PROFILE(SMBwriteX);
4503 END_PROFILE(SMBwriteX);
4507 /****************************************************************************
4509 ****************************************************************************/
4511 void reply_lseek(struct smb_request *req)
4513 connection_struct *conn = req->conn;
4519 START_PROFILE(SMBlseek);
4522 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4523 END_PROFILE(SMBlseek);
4527 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4529 if (!check_fsp(conn, req, fsp)) {
4533 flush_write_cache(fsp, SEEK_FLUSH);
4535 mode = SVAL(req->vwv+1, 0) & 3;
4536 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4537 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4546 res = fsp->fh->pos + startpos;
4557 if (umode == SEEK_END) {
4558 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4559 if(errno == EINVAL) {
4560 SMB_OFF_T current_pos = startpos;
4562 if(fsp_stat(fsp) == -1) {
4564 map_nt_error_from_unix(errno));
4565 END_PROFILE(SMBlseek);
4569 current_pos += fsp->fsp_name->st.st_ex_size;
4571 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4576 reply_nterror(req, map_nt_error_from_unix(errno));
4577 END_PROFILE(SMBlseek);
4584 reply_outbuf(req, 2, 0);
4585 SIVAL(req->outbuf,smb_vwv0,res);
4587 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4588 fsp->fnum, (double)startpos, (double)res, mode));
4590 END_PROFILE(SMBlseek);
4594 /****************************************************************************
4596 ****************************************************************************/
4598 void reply_flush(struct smb_request *req)
4600 connection_struct *conn = req->conn;
4604 START_PROFILE(SMBflush);
4607 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4611 fnum = SVAL(req->vwv+0, 0);
4612 fsp = file_fsp(req, fnum);
4614 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4619 file_sync_all(conn);
4621 NTSTATUS status = sync_file(conn, fsp, True);
4622 if (!NT_STATUS_IS_OK(status)) {
4623 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4624 fsp_str_dbg(fsp), nt_errstr(status)));
4625 reply_nterror(req, status);
4626 END_PROFILE(SMBflush);
4631 reply_outbuf(req, 0, 0);
4633 DEBUG(3,("flush\n"));
4634 END_PROFILE(SMBflush);
4638 /****************************************************************************
4640 conn POINTER CAN BE NULL HERE !
4641 ****************************************************************************/
4643 void reply_exit(struct smb_request *req)
4645 START_PROFILE(SMBexit);
4647 file_close_pid(req->smbpid, req->vuid);
4649 reply_outbuf(req, 0, 0);
4651 DEBUG(3,("exit\n"));
4653 END_PROFILE(SMBexit);
4657 /****************************************************************************
4658 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4659 ****************************************************************************/
4661 void reply_close(struct smb_request *req)
4663 connection_struct *conn = req->conn;
4664 NTSTATUS status = NT_STATUS_OK;
4665 files_struct *fsp = NULL;
4666 START_PROFILE(SMBclose);
4669 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4670 END_PROFILE(SMBclose);
4674 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4677 * We can only use check_fsp if we know it's not a directory.
4680 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4681 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4682 END_PROFILE(SMBclose);
4686 if(fsp->is_directory) {
4688 * Special case - close NT SMB directory handle.
4690 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4691 status = close_file(req, fsp, NORMAL_CLOSE);
4695 * Close ordinary file.
4698 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4699 fsp->fh->fd, fsp->fnum,
4700 conn->num_files_open));
4703 * Take care of any time sent in the close.
4706 t = srv_make_unix_date3(req->vwv+1);
4707 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4710 * close_file() returns the unix errno if an error
4711 * was detected on close - normally this is due to
4712 * a disk full error. If not then it was probably an I/O error.
4715 status = close_file(req, fsp, NORMAL_CLOSE);
4718 if (!NT_STATUS_IS_OK(status)) {
4719 reply_nterror(req, status);
4720 END_PROFILE(SMBclose);
4724 reply_outbuf(req, 0, 0);
4725 END_PROFILE(SMBclose);
4729 /****************************************************************************
4730 Reply to a writeclose (Core+ protocol).
4731 ****************************************************************************/
4733 void reply_writeclose(struct smb_request *req)
4735 connection_struct *conn = req->conn;
4737 ssize_t nwritten = -1;
4738 NTSTATUS close_status = NT_STATUS_OK;
4741 struct timespec mtime;
4743 struct lock_struct lock;
4745 START_PROFILE(SMBwriteclose);
4748 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4749 END_PROFILE(SMBwriteclose);
4753 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4755 if (!check_fsp(conn, req, fsp)) {
4756 END_PROFILE(SMBwriteclose);
4759 if (!CHECK_WRITE(fsp)) {
4760 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4761 END_PROFILE(SMBwriteclose);
4765 numtowrite = SVAL(req->vwv+1, 0);
4766 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4767 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4768 data = (const char *)req->buf + 1;
4770 if (!fsp->print_file) {
4771 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4772 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4775 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4776 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4777 END_PROFILE(SMBwriteclose);
4782 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4784 set_close_write_time(fsp, mtime);
4787 * More insanity. W2K only closes the file if writelen > 0.
4792 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4793 "file %s\n", fsp_str_dbg(fsp)));
4794 close_status = close_file(req, fsp, NORMAL_CLOSE);
4797 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4798 fsp->fnum, (int)numtowrite, (int)nwritten,
4799 conn->num_files_open));
4801 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4802 reply_nterror(req, NT_STATUS_DISK_FULL);
4806 if(!NT_STATUS_IS_OK(close_status)) {
4807 reply_nterror(req, close_status);
4811 reply_outbuf(req, 1, 0);
4813 SSVAL(req->outbuf,smb_vwv0,nwritten);
4816 if (numtowrite && !fsp->print_file) {
4817 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4820 END_PROFILE(SMBwriteclose);
4825 #define DBGC_CLASS DBGC_LOCKING
4827 /****************************************************************************
4829 ****************************************************************************/
4831 void reply_lock(struct smb_request *req)
4833 connection_struct *conn = req->conn;
4834 uint64_t count,offset;
4837 struct byte_range_lock *br_lck = NULL;
4839 START_PROFILE(SMBlock);
4842 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4843 END_PROFILE(SMBlock);
4847 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4849 if (!check_fsp(conn, req, fsp)) {
4850 END_PROFILE(SMBlock);
4854 count = (uint64_t)IVAL(req->vwv+1, 0);
4855 offset = (uint64_t)IVAL(req->vwv+3, 0);
4857 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4858 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4860 br_lck = do_lock(req->sconn->msg_ctx,
4862 (uint64_t)req->smbpid,
4867 False, /* Non-blocking lock. */
4872 TALLOC_FREE(br_lck);
4874 if (NT_STATUS_V(status)) {
4875 reply_nterror(req, status);
4876 END_PROFILE(SMBlock);
4880 reply_outbuf(req, 0, 0);
4882 END_PROFILE(SMBlock);
4886 /****************************************************************************
4888 ****************************************************************************/
4890 void reply_unlock(struct smb_request *req)
4892 connection_struct *conn = req->conn;
4893 uint64_t count,offset;
4897 START_PROFILE(SMBunlock);
4900 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4901 END_PROFILE(SMBunlock);
4905 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4907 if (!check_fsp(conn, req, fsp)) {
4908 END_PROFILE(SMBunlock);
4912 count = (uint64_t)IVAL(req->vwv+1, 0);
4913 offset = (uint64_t)IVAL(req->vwv+3, 0);
4915 status = do_unlock(req->sconn->msg_ctx,
4917 (uint64_t)req->smbpid,
4922 if (NT_STATUS_V(status)) {
4923 reply_nterror(req, status);
4924 END_PROFILE(SMBunlock);
4928 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4929 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4931 reply_outbuf(req, 0, 0);
4933 END_PROFILE(SMBunlock);
4938 #define DBGC_CLASS DBGC_ALL
4940 /****************************************************************************
4942 conn POINTER CAN BE NULL HERE !
4943 ****************************************************************************/
4945 void reply_tdis(struct smb_request *req)
4947 connection_struct *conn = req->conn;
4948 START_PROFILE(SMBtdis);
4951 DEBUG(4,("Invalid connection in tdis\n"));
4952 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
4953 END_PROFILE(SMBtdis);
4959 close_cnum(conn,req->vuid);
4962 reply_outbuf(req, 0, 0);
4963 END_PROFILE(SMBtdis);
4967 /****************************************************************************
4969 conn POINTER CAN BE NULL HERE !
4970 ****************************************************************************/
4972 void reply_echo(struct smb_request *req)
4974 connection_struct *conn = req->conn;
4975 struct smb_perfcount_data local_pcd;
4976 struct smb_perfcount_data *cur_pcd;
4980 START_PROFILE(SMBecho);
4982 smb_init_perfcount_data(&local_pcd);
4985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4986 END_PROFILE(SMBecho);
4990 smb_reverb = SVAL(req->vwv+0, 0);
4992 reply_outbuf(req, 1, req->buflen);
4994 /* copy any incoming data back out */
4995 if (req->buflen > 0) {
4996 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4999 if (smb_reverb > 100) {
5000 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5004 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5006 /* this makes sure we catch the request pcd */
5007 if (seq_num == smb_reverb) {
5008 cur_pcd = &req->pcd;
5010 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5011 cur_pcd = &local_pcd;
5014 SSVAL(req->outbuf,smb_vwv0,seq_num);
5016 show_msg((char *)req->outbuf);
5017 if (!srv_send_smb(smbd_server_fd(),
5018 (char *)req->outbuf,
5019 true, req->seqnum+1,
5020 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5022 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5025 DEBUG(3,("echo %d times\n", smb_reverb));
5027 TALLOC_FREE(req->outbuf);
5029 END_PROFILE(SMBecho);
5033 /****************************************************************************
5034 Reply to a printopen.
5035 ****************************************************************************/
5037 void reply_printopen(struct smb_request *req)
5039 connection_struct *conn = req->conn;
5043 START_PROFILE(SMBsplopen);
5046 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5047 END_PROFILE(SMBsplopen);
5051 if (!CAN_PRINT(conn)) {
5052 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5053 END_PROFILE(SMBsplopen);
5057 status = file_new(req, conn, &fsp);
5058 if(!NT_STATUS_IS_OK(status)) {
5059 reply_nterror(req, status);
5060 END_PROFILE(SMBsplopen);
5064 /* Open for exclusive use, write only. */
5065 status = print_spool_open(fsp, NULL, req->vuid);
5067 if (!NT_STATUS_IS_OK(status)) {
5068 file_free(req, fsp);
5069 reply_nterror(req, status);
5070 END_PROFILE(SMBsplopen);
5074 reply_outbuf(req, 1, 0);
5075 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5077 DEBUG(3,("openprint fd=%d fnum=%d\n",
5078 fsp->fh->fd, fsp->fnum));
5080 END_PROFILE(SMBsplopen);
5084 /****************************************************************************
5085 Reply to a printclose.
5086 ****************************************************************************/
5088 void reply_printclose(struct smb_request *req)
5090 connection_struct *conn = req->conn;
5094 START_PROFILE(SMBsplclose);
5097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5098 END_PROFILE(SMBsplclose);
5102 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5104 if (!check_fsp(conn, req, fsp)) {
5105 END_PROFILE(SMBsplclose);
5109 if (!CAN_PRINT(conn)) {
5110 reply_force_doserror(req, ERRSRV, ERRerror);
5111 END_PROFILE(SMBsplclose);
5115 DEBUG(3,("printclose fd=%d fnum=%d\n",
5116 fsp->fh->fd,fsp->fnum));
5118 status = close_file(req, fsp, NORMAL_CLOSE);
5120 if(!NT_STATUS_IS_OK(status)) {
5121 reply_nterror(req, status);
5122 END_PROFILE(SMBsplclose);
5126 reply_outbuf(req, 0, 0);
5128 END_PROFILE(SMBsplclose);
5132 /****************************************************************************
5133 Reply to a printqueue.
5134 ****************************************************************************/
5136 void reply_printqueue(struct smb_request *req)
5138 connection_struct *conn = req->conn;
5142 START_PROFILE(SMBsplretq);
5145 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5146 END_PROFILE(SMBsplretq);
5150 max_count = SVAL(req->vwv+0, 0);
5151 start_index = SVAL(req->vwv+1, 0);
5153 /* we used to allow the client to get the cnum wrong, but that
5154 is really quite gross and only worked when there was only
5155 one printer - I think we should now only accept it if they
5156 get it right (tridge) */
5157 if (!CAN_PRINT(conn)) {
5158 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5159 END_PROFILE(SMBsplretq);
5163 reply_outbuf(req, 2, 3);
5164 SSVAL(req->outbuf,smb_vwv0,0);
5165 SSVAL(req->outbuf,smb_vwv1,0);
5166 SCVAL(smb_buf(req->outbuf),0,1);
5167 SSVAL(smb_buf(req->outbuf),1,0);
5169 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5170 start_index, max_count));
5173 TALLOC_CTX *mem_ctx = talloc_tos();
5176 const char *sharename = lp_servicename(SNUM(conn));
5177 struct rpc_pipe_client *cli = NULL;
5178 struct policy_handle handle;
5179 struct spoolss_DevmodeContainer devmode_ctr;
5180 union spoolss_JobInfo *info;
5182 uint32_t num_to_get;
5186 ZERO_STRUCT(handle);
5188 status = rpc_connect_spoolss_pipe(conn, &cli);
5189 if (!NT_STATUS_IS_OK(status)) {
5190 DEBUG(0, ("reply_printqueue: "
5191 "could not connect to spoolss: %s\n",
5192 nt_errstr(status)));
5193 reply_nterror(req, status);
5197 ZERO_STRUCT(devmode_ctr);
5199 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
5202 SEC_FLAG_MAXIMUM_ALLOWED,
5205 if (!NT_STATUS_IS_OK(status)) {
5206 reply_nterror(req, status);
5209 if (!W_ERROR_IS_OK(werr)) {
5210 reply_nterror(req, werror_to_ntstatus(werr));
5214 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5222 if (!W_ERROR_IS_OK(werr)) {
5223 reply_nterror(req, werror_to_ntstatus(werr));
5227 if (max_count > 0) {
5228 first = start_index;
5230 first = start_index + max_count + 1;
5233 if (first >= count) {
5236 num_to_get = first + MIN(ABS(max_count), count - first);
5239 for (i = first; i < num_to_get; i++) {
5242 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5244 uint16_t qrapjobid = pjobid_to_rap(sharename,
5245 info[i].info2.job_id);
5247 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5253 srv_put_dos_date2(p, 0, qtime);
5254 SCVAL(p, 4, qstatus);
5255 SSVAL(p, 5, qrapjobid);
5256 SIVAL(p, 7, info[i].info2.size);
5258 srvstr_push(blob, req->flags2, p+12,
5259 info[i].info2.notify_name, 16, STR_ASCII);
5261 if (message_push_blob(
5264 blob, sizeof(blob))) == -1) {
5265 reply_nterror(req, NT_STATUS_NO_MEMORY);
5271 SSVAL(req->outbuf,smb_vwv0,count);
5272 SSVAL(req->outbuf,smb_vwv1,
5273 (max_count>0?first+count:first-1));
5274 SCVAL(smb_buf(req->outbuf),0,1);
5275 SSVAL(smb_buf(req->outbuf),1,28*count);
5279 DEBUG(3, ("%u entries returned in queue\n",
5283 if (cli && is_valid_policy_hnd(&handle)) {
5284 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
5289 END_PROFILE(SMBsplretq);
5293 /****************************************************************************
5294 Reply to a printwrite.
5295 ****************************************************************************/
5297 void reply_printwrite(struct smb_request *req)
5299 connection_struct *conn = req->conn;
5304 START_PROFILE(SMBsplwr);
5307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5308 END_PROFILE(SMBsplwr);
5312 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5314 if (!check_fsp(conn, req, fsp)) {
5315 END_PROFILE(SMBsplwr);
5319 if (!fsp->print_file) {
5320 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5321 END_PROFILE(SMBsplwr);
5325 if (!CHECK_WRITE(fsp)) {
5326 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5327 END_PROFILE(SMBsplwr);
5331 numtowrite = SVAL(req->buf, 1);
5333 if (req->buflen < numtowrite + 3) {
5334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5335 END_PROFILE(SMBsplwr);
5339 data = (const char *)req->buf + 3;
5341 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5342 reply_nterror(req, map_nt_error_from_unix(errno));
5343 END_PROFILE(SMBsplwr);
5347 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5349 END_PROFILE(SMBsplwr);
5353 /****************************************************************************
5355 ****************************************************************************/
5357 void reply_mkdir(struct smb_request *req)
5359 connection_struct *conn = req->conn;
5360 struct smb_filename *smb_dname = NULL;
5361 char *directory = NULL;
5363 TALLOC_CTX *ctx = talloc_tos();
5365 START_PROFILE(SMBmkdir);
5367 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5368 STR_TERMINATE, &status);
5369 if (!NT_STATUS_IS_OK(status)) {
5370 reply_nterror(req, status);
5374 status = filename_convert(ctx, conn,
5375 req->flags2 & FLAGS2_DFS_PATHNAMES,
5380 if (!NT_STATUS_IS_OK(status)) {
5381 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5382 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5383 ERRSRV, ERRbadpath);
5386 reply_nterror(req, status);
5390 status = create_directory(conn, req, smb_dname);
5392 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5394 if (!NT_STATUS_IS_OK(status)) {
5396 if (!use_nt_status()
5397 && NT_STATUS_EQUAL(status,
5398 NT_STATUS_OBJECT_NAME_COLLISION)) {
5400 * Yes, in the DOS error code case we get a
5401 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5402 * samba4 torture test.
5404 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5407 reply_nterror(req, status);
5411 reply_outbuf(req, 0, 0);
5413 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5415 TALLOC_FREE(smb_dname);
5416 END_PROFILE(SMBmkdir);
5420 /****************************************************************************
5422 ****************************************************************************/
5424 void reply_rmdir(struct smb_request *req)
5426 connection_struct *conn = req->conn;
5427 struct smb_filename *smb_dname = NULL;
5428 char *directory = NULL;
5430 TALLOC_CTX *ctx = talloc_tos();
5431 files_struct *fsp = NULL;
5433 struct smbd_server_connection *sconn = req->sconn;
5435 START_PROFILE(SMBrmdir);
5437 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5438 STR_TERMINATE, &status);
5439 if (!NT_STATUS_IS_OK(status)) {
5440 reply_nterror(req, status);
5444 status = filename_convert(ctx, conn,
5445 req->flags2 & FLAGS2_DFS_PATHNAMES,
5450 if (!NT_STATUS_IS_OK(status)) {
5451 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5452 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5453 ERRSRV, ERRbadpath);
5456 reply_nterror(req, status);
5460 if (is_ntfs_stream_smb_fname(smb_dname)) {
5461 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5465 status = SMB_VFS_CREATE_FILE(
5468 0, /* root_dir_fid */
5469 smb_dname, /* fname */
5470 DELETE_ACCESS, /* access_mask */
5471 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5473 FILE_OPEN, /* create_disposition*/
5474 FILE_DIRECTORY_FILE, /* create_options */
5475 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5476 0, /* oplock_request */
5477 0, /* allocation_size */
5478 0, /* private_flags */
5484 if (!NT_STATUS_IS_OK(status)) {
5485 if (open_was_deferred(req->mid)) {
5486 /* We have re-scheduled this call. */
5489 reply_nterror(req, status);
5493 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5494 if (!NT_STATUS_IS_OK(status)) {
5495 close_file(req, fsp, ERROR_CLOSE);
5496 reply_nterror(req, status);
5500 if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
5501 close_file(req, fsp, ERROR_CLOSE);
5502 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5506 status = close_file(req, fsp, NORMAL_CLOSE);
5507 if (!NT_STATUS_IS_OK(status)) {
5508 reply_nterror(req, status);
5510 reply_outbuf(req, 0, 0);
5513 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5515 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5517 TALLOC_FREE(smb_dname);
5518 END_PROFILE(SMBrmdir);
5522 /*******************************************************************
5523 Resolve wildcards in a filename rename.
5524 ********************************************************************/
5526 static bool resolve_wildcards(TALLOC_CTX *ctx,
5531 char *name2_copy = NULL;
5536 char *p,*p2, *pname1, *pname2;
5538 name2_copy = talloc_strdup(ctx, name2);
5543 pname1 = strrchr_m(name1,'/');
5544 pname2 = strrchr_m(name2_copy,'/');
5546 if (!pname1 || !pname2) {
5550 /* Truncate the copy of name2 at the last '/' */
5553 /* Now go past the '/' */
5557 root1 = talloc_strdup(ctx, pname1);
5558 root2 = talloc_strdup(ctx, pname2);
5560 if (!root1 || !root2) {
5564 p = strrchr_m(root1,'.');
5567 ext1 = talloc_strdup(ctx, p+1);
5569 ext1 = talloc_strdup(ctx, "");
5571 p = strrchr_m(root2,'.');
5574 ext2 = talloc_strdup(ctx, p+1);
5576 ext2 = talloc_strdup(ctx, "");
5579 if (!ext1 || !ext2) {
5587 /* Hmmm. Should this be mb-aware ? */
5590 } else if (*p2 == '*') {
5592 root2 = talloc_asprintf(ctx, "%s%s",
5611 /* Hmmm. Should this be mb-aware ? */
5614 } else if (*p2 == '*') {
5616 ext2 = talloc_asprintf(ctx, "%s%s",
5632 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5637 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5649 /****************************************************************************
5650 Ensure open files have their names updated. Updated to notify other smbd's
5652 ****************************************************************************/
5654 static void rename_open_files(connection_struct *conn,
5655 struct share_mode_lock *lck,
5656 const struct smb_filename *smb_fname_dst)
5659 bool did_rename = False;
5662 for(fsp = file_find_di_first(lck->id); fsp;
5663 fsp = file_find_di_next(fsp)) {
5664 /* fsp_name is a relative path under the fsp. To change this for other
5665 sharepaths we need to manipulate relative paths. */
5666 /* TODO - create the absolute path and manipulate the newname
5667 relative to the sharepath. */
5668 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5671 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5672 "(file_id %s) from %s -> %s\n", fsp->fnum,
5673 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5674 smb_fname_str_dbg(smb_fname_dst)));
5676 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5677 if (NT_STATUS_IS_OK(status)) {
5683 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5684 "for %s\n", file_id_string_tos(&lck->id),
5685 smb_fname_str_dbg(smb_fname_dst)));
5688 /* Send messages to all smbd's (not ourself) that the name has changed. */
5689 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5694 /****************************************************************************
5695 We need to check if the source path is a parent directory of the destination
5696 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5697 refuse the rename with a sharing violation. Under UNIX the above call can
5698 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5699 probably need to check that the client is a Windows one before disallowing
5700 this as a UNIX client (one with UNIX extensions) can know the source is a
5701 symlink and make this decision intelligently. Found by an excellent bug
5702 report from <AndyLiebman@aol.com>.
5703 ****************************************************************************/
5705 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5706 const struct smb_filename *smb_fname_dst)
5708 const char *psrc = smb_fname_src->base_name;
5709 const char *pdst = smb_fname_dst->base_name;
5712 if (psrc[0] == '.' && psrc[1] == '/') {
5715 if (pdst[0] == '.' && pdst[1] == '/') {
5718 if ((slen = strlen(psrc)) > strlen(pdst)) {
5721 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5725 * Do the notify calls from a rename
5728 static void notify_rename(connection_struct *conn, bool is_dir,
5729 const struct smb_filename *smb_fname_src,
5730 const struct smb_filename *smb_fname_dst)
5732 char *parent_dir_src = NULL;
5733 char *parent_dir_dst = NULL;
5736 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5737 : FILE_NOTIFY_CHANGE_FILE_NAME;
5739 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5740 &parent_dir_src, NULL) ||
5741 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5742 &parent_dir_dst, NULL)) {
5746 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5747 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5748 smb_fname_src->base_name);
5749 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5750 smb_fname_dst->base_name);
5753 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5754 smb_fname_src->base_name);
5755 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5756 smb_fname_dst->base_name);
5759 /* this is a strange one. w2k3 gives an additional event for
5760 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5761 files, but not directories */
5763 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5764 FILE_NOTIFY_CHANGE_ATTRIBUTES
5765 |FILE_NOTIFY_CHANGE_CREATION,
5766 smb_fname_dst->base_name);
5769 TALLOC_FREE(parent_dir_src);
5770 TALLOC_FREE(parent_dir_dst);
5773 /****************************************************************************
5774 Rename an open file - given an fsp.
5775 ****************************************************************************/
5777 NTSTATUS rename_internals_fsp(connection_struct *conn,
5779 const struct smb_filename *smb_fname_dst_in,
5781 bool replace_if_exists)
5783 TALLOC_CTX *ctx = talloc_tos();
5784 struct smb_filename *smb_fname_dst = NULL;
5785 NTSTATUS status = NT_STATUS_OK;
5786 struct share_mode_lock *lck = NULL;
5787 bool dst_exists, old_is_stream, new_is_stream;
5789 status = check_name(conn, smb_fname_dst_in->base_name);
5790 if (!NT_STATUS_IS_OK(status)) {
5794 /* Make a copy of the dst smb_fname structs */
5796 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5797 if (!NT_STATUS_IS_OK(status)) {
5801 /* Ensure the dst smb_fname contains a '/' */
5802 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5804 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5805 smb_fname_dst->base_name);
5807 status = NT_STATUS_NO_MEMORY;
5810 TALLOC_FREE(smb_fname_dst->base_name);
5811 smb_fname_dst->base_name = tmp;
5815 * Check for special case with case preserving and not
5816 * case sensitive. If the old last component differs from the original
5817 * last component only by case, then we should allow
5818 * the rename (user is trying to change the case of the
5821 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5822 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5823 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5825 char *fname_dst_lcomp_base_mod = NULL;
5826 struct smb_filename *smb_fname_orig_lcomp = NULL;
5829 * Get the last component of the destination name. Note that
5830 * we guarantee that destination name contains a '/' character
5833 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5834 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5835 if (!fname_dst_lcomp_base_mod) {
5836 status = NT_STATUS_NO_MEMORY;
5841 * Create an smb_filename struct using the original last
5842 * component of the destination.
5844 status = create_synthetic_smb_fname_split(ctx,
5845 smb_fname_dst->original_lcomp, NULL,
5846 &smb_fname_orig_lcomp);
5847 if (!NT_STATUS_IS_OK(status)) {
5848 TALLOC_FREE(fname_dst_lcomp_base_mod);
5852 /* If the base names only differ by case, use original. */
5853 if(!strcsequal(fname_dst_lcomp_base_mod,
5854 smb_fname_orig_lcomp->base_name)) {
5857 * Replace the modified last component with the
5860 *last_slash = '\0'; /* Truncate at the '/' */
5861 tmp = talloc_asprintf(smb_fname_dst,
5863 smb_fname_dst->base_name,
5864 smb_fname_orig_lcomp->base_name);
5866 status = NT_STATUS_NO_MEMORY;
5867 TALLOC_FREE(fname_dst_lcomp_base_mod);
5868 TALLOC_FREE(smb_fname_orig_lcomp);
5871 TALLOC_FREE(smb_fname_dst->base_name);
5872 smb_fname_dst->base_name = tmp;
5875 /* If the stream_names only differ by case, use original. */
5876 if(!strcsequal(smb_fname_dst->stream_name,
5877 smb_fname_orig_lcomp->stream_name)) {
5879 /* Use the original stream. */
5880 tmp = talloc_strdup(smb_fname_dst,
5881 smb_fname_orig_lcomp->stream_name);
5883 status = NT_STATUS_NO_MEMORY;
5884 TALLOC_FREE(fname_dst_lcomp_base_mod);
5885 TALLOC_FREE(smb_fname_orig_lcomp);
5888 TALLOC_FREE(smb_fname_dst->stream_name);
5889 smb_fname_dst->stream_name = tmp;
5891 TALLOC_FREE(fname_dst_lcomp_base_mod);
5892 TALLOC_FREE(smb_fname_orig_lcomp);
5896 * If the src and dest names are identical - including case,
5897 * don't do the rename, just return success.
5900 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5901 strcsequal(fsp->fsp_name->stream_name,
5902 smb_fname_dst->stream_name)) {
5903 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5904 "- returning success\n",
5905 smb_fname_str_dbg(smb_fname_dst)));
5906 status = NT_STATUS_OK;
5910 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
5911 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5913 /* Return the correct error code if both names aren't streams. */
5914 if (!old_is_stream && new_is_stream) {
5915 status = NT_STATUS_OBJECT_NAME_INVALID;
5919 if (old_is_stream && !new_is_stream) {
5920 status = NT_STATUS_INVALID_PARAMETER;
5924 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
5926 if(!replace_if_exists && dst_exists) {
5927 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
5928 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5929 smb_fname_str_dbg(smb_fname_dst)));
5930 status = NT_STATUS_OBJECT_NAME_COLLISION;
5935 struct file_id fileid = vfs_file_id_from_sbuf(conn,
5936 &smb_fname_dst->st);
5937 files_struct *dst_fsp = file_find_di_first(fileid);
5938 /* The file can be open when renaming a stream */
5939 if (dst_fsp && !new_is_stream) {
5940 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5941 status = NT_STATUS_ACCESS_DENIED;
5946 /* Ensure we have a valid stat struct for the source. */
5947 status = vfs_stat_fsp(fsp);
5948 if (!NT_STATUS_IS_OK(status)) {
5952 status = can_rename(conn, fsp, attrs);
5954 if (!NT_STATUS_IS_OK(status)) {
5955 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
5956 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
5957 smb_fname_str_dbg(smb_fname_dst)));
5958 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5959 status = NT_STATUS_ACCESS_DENIED;
5963 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
5964 status = NT_STATUS_ACCESS_DENIED;
5967 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5971 * We have the file open ourselves, so not being able to get the
5972 * corresponding share mode lock is a fatal error.
5975 SMB_ASSERT(lck != NULL);
5977 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
5978 uint32 create_options = fsp->fh->private_options;
5980 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
5981 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5982 smb_fname_str_dbg(smb_fname_dst)));
5984 if (lp_map_archive(SNUM(conn)) ||
5985 lp_store_dos_attributes(SNUM(conn))) {
5986 /* We must set the archive bit on the newly
5988 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
5989 uint32_t old_dosmode = dos_mode(conn,
5991 file_set_dosmode(conn,
5993 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
5999 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6002 rename_open_files(conn, lck, smb_fname_dst);
6005 * A rename acts as a new file create w.r.t. allowing an initial delete
6006 * on close, probably because in Windows there is a new handle to the
6007 * new file. If initial delete on close was requested but not
6008 * originally set, we need to set it here. This is probably not 100% correct,
6009 * but will work for the CIFSFS client which in non-posix mode
6010 * depends on these semantics. JRA.
6013 if (create_options & FILE_DELETE_ON_CLOSE) {
6014 status = can_set_delete_on_close(fsp, 0);
6016 if (NT_STATUS_IS_OK(status)) {
6017 /* Note that here we set the *inital* delete on close flag,
6018 * not the regular one. The magic gets handled in close. */
6019 fsp->initial_delete_on_close = True;
6023 status = NT_STATUS_OK;
6029 if (errno == ENOTDIR || errno == EISDIR) {
6030 status = NT_STATUS_OBJECT_NAME_COLLISION;
6032 status = map_nt_error_from_unix(errno);
6035 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6036 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6037 smb_fname_str_dbg(smb_fname_dst)));
6040 TALLOC_FREE(smb_fname_dst);
6045 /****************************************************************************
6046 The guts of the rename command, split out so it may be called by the NT SMB
6048 ****************************************************************************/
6050 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6051 connection_struct *conn,
6052 struct smb_request *req,
6053 struct smb_filename *smb_fname_src,
6054 struct smb_filename *smb_fname_dst,
6056 bool replace_if_exists,
6059 uint32_t access_mask)
6061 char *fname_src_dir = NULL;
6062 char *fname_src_mask = NULL;
6064 NTSTATUS status = NT_STATUS_OK;
6065 struct smb_Dir *dir_hnd = NULL;
6066 const char *dname = NULL;
6067 char *talloced = NULL;
6069 int create_options = 0;
6070 bool posix_pathnames = lp_posix_pathnames();
6073 * Split the old name into directory and last component
6074 * strings. Note that unix_convert may have stripped off a
6075 * leading ./ from both name and newname if the rename is
6076 * at the root of the share. We need to make sure either both
6077 * name and newname contain a / character or neither of them do
6078 * as this is checked in resolve_wildcards().
6081 /* Split up the directory from the filename/mask. */
6082 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6083 &fname_src_dir, &fname_src_mask);
6084 if (!NT_STATUS_IS_OK(status)) {
6085 status = NT_STATUS_NO_MEMORY;
6090 * We should only check the mangled cache
6091 * here if unix_convert failed. This means
6092 * that the path in 'mask' doesn't exist
6093 * on the file system and so we need to look
6094 * for a possible mangle. This patch from
6095 * Tine Smukavec <valentin.smukavec@hermes.si>.
6098 if (!VALID_STAT(smb_fname_src->st) &&
6099 mangle_is_mangled(fname_src_mask, conn->params)) {
6100 char *new_mask = NULL;
6101 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6104 TALLOC_FREE(fname_src_mask);
6105 fname_src_mask = new_mask;
6109 if (!src_has_wild) {
6113 * Only one file needs to be renamed. Append the mask back
6114 * onto the directory.
6116 TALLOC_FREE(smb_fname_src->base_name);
6117 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6121 if (!smb_fname_src->base_name) {
6122 status = NT_STATUS_NO_MEMORY;
6126 /* Ensure dst fname contains a '/' also */
6127 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6129 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6130 smb_fname_dst->base_name);
6132 status = NT_STATUS_NO_MEMORY;
6135 TALLOC_FREE(smb_fname_dst->base_name);
6136 smb_fname_dst->base_name = tmp;
6139 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6140 "case_preserve = %d, short case preserve = %d, "
6141 "directory = %s, newname = %s, "
6142 "last_component_dest = %s\n",
6143 conn->case_sensitive, conn->case_preserve,
6144 conn->short_case_preserve,
6145 smb_fname_str_dbg(smb_fname_src),
6146 smb_fname_str_dbg(smb_fname_dst),
6147 smb_fname_dst->original_lcomp));
6149 /* The dest name still may have wildcards. */
6150 if (dest_has_wild) {
6151 char *fname_dst_mod = NULL;
6152 if (!resolve_wildcards(smb_fname_dst,
6153 smb_fname_src->base_name,
6154 smb_fname_dst->base_name,
6156 DEBUG(6, ("rename_internals: resolve_wildcards "
6158 smb_fname_src->base_name,
6159 smb_fname_dst->base_name));
6160 status = NT_STATUS_NO_MEMORY;
6163 TALLOC_FREE(smb_fname_dst->base_name);
6164 smb_fname_dst->base_name = fname_dst_mod;
6167 ZERO_STRUCT(smb_fname_src->st);
6168 if (posix_pathnames) {
6169 SMB_VFS_LSTAT(conn, smb_fname_src);
6171 SMB_VFS_STAT(conn, smb_fname_src);
6174 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6175 create_options |= FILE_DIRECTORY_FILE;
6178 status = SMB_VFS_CREATE_FILE(
6181 0, /* root_dir_fid */
6182 smb_fname_src, /* fname */
6183 access_mask, /* access_mask */
6184 (FILE_SHARE_READ | /* share_access */
6186 FILE_OPEN, /* create_disposition*/
6187 create_options, /* create_options */
6188 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6189 0, /* oplock_request */
6190 0, /* allocation_size */
6191 0, /* private_flags */
6197 if (!NT_STATUS_IS_OK(status)) {
6198 DEBUG(3, ("Could not open rename source %s: %s\n",
6199 smb_fname_str_dbg(smb_fname_src),
6200 nt_errstr(status)));
6204 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6205 attrs, replace_if_exists);
6207 close_file(req, fsp, NORMAL_CLOSE);
6209 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6210 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6211 smb_fname_str_dbg(smb_fname_dst)));
6217 * Wildcards - process each file that matches.
6219 if (strequal(fname_src_mask, "????????.???")) {
6220 TALLOC_FREE(fname_src_mask);
6221 fname_src_mask = talloc_strdup(ctx, "*");
6222 if (!fname_src_mask) {
6223 status = NT_STATUS_NO_MEMORY;
6228 status = check_name(conn, fname_src_dir);
6229 if (!NT_STATUS_IS_OK(status)) {
6233 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6235 if (dir_hnd == NULL) {
6236 status = map_nt_error_from_unix(errno);
6240 status = NT_STATUS_NO_SUCH_FILE;
6242 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6243 * - gentest fix. JRA
6246 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6248 files_struct *fsp = NULL;
6249 char *destname = NULL;
6250 bool sysdir_entry = False;
6252 /* Quick check for "." and ".." */
6253 if (ISDOT(dname) || ISDOTDOT(dname)) {
6255 sysdir_entry = True;
6257 TALLOC_FREE(talloced);
6262 if (!is_visible_file(conn, fname_src_dir, dname,
6263 &smb_fname_src->st, false)) {
6264 TALLOC_FREE(talloced);
6268 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6269 TALLOC_FREE(talloced);
6274 status = NT_STATUS_OBJECT_NAME_INVALID;
6278 TALLOC_FREE(smb_fname_src->base_name);
6279 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6283 if (!smb_fname_src->base_name) {
6284 status = NT_STATUS_NO_MEMORY;
6288 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6289 smb_fname_dst->base_name,
6291 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6292 smb_fname_src->base_name, destname));
6293 TALLOC_FREE(talloced);
6297 status = NT_STATUS_NO_MEMORY;
6301 TALLOC_FREE(smb_fname_dst->base_name);
6302 smb_fname_dst->base_name = destname;
6304 ZERO_STRUCT(smb_fname_src->st);
6305 if (posix_pathnames) {
6306 SMB_VFS_LSTAT(conn, smb_fname_src);
6308 SMB_VFS_STAT(conn, smb_fname_src);
6313 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6314 create_options |= FILE_DIRECTORY_FILE;
6317 status = SMB_VFS_CREATE_FILE(
6320 0, /* root_dir_fid */
6321 smb_fname_src, /* fname */
6322 access_mask, /* access_mask */
6323 (FILE_SHARE_READ | /* share_access */
6325 FILE_OPEN, /* create_disposition*/
6326 create_options, /* create_options */
6327 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6328 0, /* oplock_request */
6329 0, /* allocation_size */
6330 0, /* private_flags */
6336 if (!NT_STATUS_IS_OK(status)) {
6337 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6338 "returned %s rename %s -> %s\n",
6340 smb_fname_str_dbg(smb_fname_src),
6341 smb_fname_str_dbg(smb_fname_dst)));
6345 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6347 if (!smb_fname_dst->original_lcomp) {
6348 status = NT_STATUS_NO_MEMORY;
6352 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6353 attrs, replace_if_exists);
6355 close_file(req, fsp, NORMAL_CLOSE);
6357 if (!NT_STATUS_IS_OK(status)) {
6358 DEBUG(3, ("rename_internals_fsp returned %s for "
6359 "rename %s -> %s\n", nt_errstr(status),
6360 smb_fname_str_dbg(smb_fname_src),
6361 smb_fname_str_dbg(smb_fname_dst)));
6367 DEBUG(3,("rename_internals: doing rename on %s -> "
6368 "%s\n", smb_fname_str_dbg(smb_fname_src),
6369 smb_fname_str_dbg(smb_fname_src)));
6370 TALLOC_FREE(talloced);
6372 TALLOC_FREE(dir_hnd);
6374 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6375 status = map_nt_error_from_unix(errno);
6379 TALLOC_FREE(talloced);
6380 TALLOC_FREE(fname_src_dir);
6381 TALLOC_FREE(fname_src_mask);
6385 /****************************************************************************
6387 ****************************************************************************/
6389 void reply_mv(struct smb_request *req)
6391 connection_struct *conn = req->conn;
6393 char *newname = NULL;
6397 bool src_has_wcard = False;
6398 bool dest_has_wcard = False;
6399 TALLOC_CTX *ctx = talloc_tos();
6400 struct smb_filename *smb_fname_src = NULL;
6401 struct smb_filename *smb_fname_dst = NULL;
6403 START_PROFILE(SMBmv);
6406 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6410 attrs = SVAL(req->vwv+0, 0);
6412 p = (const char *)req->buf + 1;
6413 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6414 &status, &src_has_wcard);
6415 if (!NT_STATUS_IS_OK(status)) {
6416 reply_nterror(req, status);
6420 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6421 &status, &dest_has_wcard);
6422 if (!NT_STATUS_IS_OK(status)) {
6423 reply_nterror(req, status);
6427 status = filename_convert(ctx,
6429 req->flags2 & FLAGS2_DFS_PATHNAMES,
6431 UCF_COND_ALLOW_WCARD_LCOMP,
6435 if (!NT_STATUS_IS_OK(status)) {
6436 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6437 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6438 ERRSRV, ERRbadpath);
6441 reply_nterror(req, status);
6445 status = filename_convert(ctx,
6447 req->flags2 & FLAGS2_DFS_PATHNAMES,
6449 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6453 if (!NT_STATUS_IS_OK(status)) {
6454 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6455 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6456 ERRSRV, ERRbadpath);
6459 reply_nterror(req, status);
6463 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6464 smb_fname_str_dbg(smb_fname_dst)));
6466 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6467 attrs, False, src_has_wcard, dest_has_wcard,
6469 if (!NT_STATUS_IS_OK(status)) {
6470 if (open_was_deferred(req->mid)) {
6471 /* We have re-scheduled this call. */
6474 reply_nterror(req, status);
6478 reply_outbuf(req, 0, 0);
6480 TALLOC_FREE(smb_fname_src);
6481 TALLOC_FREE(smb_fname_dst);
6486 /*******************************************************************
6487 Copy a file as part of a reply_copy.
6488 ******************************************************************/
6491 * TODO: check error codes on all callers
6494 NTSTATUS copy_file(TALLOC_CTX *ctx,
6495 connection_struct *conn,
6496 struct smb_filename *smb_fname_src,
6497 struct smb_filename *smb_fname_dst,
6500 bool target_is_directory)
6502 struct smb_filename *smb_fname_dst_tmp = NULL;
6504 files_struct *fsp1,*fsp2;
6506 uint32 new_create_disposition;
6510 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6511 if (!NT_STATUS_IS_OK(status)) {
6516 * If the target is a directory, extract the last component from the
6517 * src filename and append it to the dst filename
6519 if (target_is_directory) {
6522 /* dest/target can't be a stream if it's a directory. */
6523 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6525 p = strrchr_m(smb_fname_src->base_name,'/');
6529 p = smb_fname_src->base_name;
6531 smb_fname_dst_tmp->base_name =
6532 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6534 if (!smb_fname_dst_tmp->base_name) {
6535 status = NT_STATUS_NO_MEMORY;
6540 status = vfs_file_exist(conn, smb_fname_src);
6541 if (!NT_STATUS_IS_OK(status)) {
6545 if (!target_is_directory && count) {
6546 new_create_disposition = FILE_OPEN;
6548 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6550 &new_create_disposition,
6553 status = NT_STATUS_INVALID_PARAMETER;
6558 /* Open the src file for reading. */
6559 status = SMB_VFS_CREATE_FILE(
6562 0, /* root_dir_fid */
6563 smb_fname_src, /* fname */
6564 FILE_GENERIC_READ, /* access_mask */
6565 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6566 FILE_OPEN, /* create_disposition*/
6567 0, /* create_options */
6568 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6569 INTERNAL_OPEN_ONLY, /* oplock_request */
6570 0, /* allocation_size */
6571 0, /* private_flags */
6577 if (!NT_STATUS_IS_OK(status)) {
6581 dosattrs = dos_mode(conn, smb_fname_src);
6583 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6584 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6587 /* Open the dst file for writing. */
6588 status = SMB_VFS_CREATE_FILE(
6591 0, /* root_dir_fid */
6592 smb_fname_dst, /* fname */
6593 FILE_GENERIC_WRITE, /* access_mask */
6594 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6595 new_create_disposition, /* create_disposition*/
6596 0, /* create_options */
6597 dosattrs, /* file_attributes */
6598 INTERNAL_OPEN_ONLY, /* oplock_request */
6599 0, /* allocation_size */
6600 0, /* private_flags */
6606 if (!NT_STATUS_IS_OK(status)) {
6607 close_file(NULL, fsp1, ERROR_CLOSE);
6611 if ((ofun&3) == 1) {
6612 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6613 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6615 * Stop the copy from occurring.
6618 smb_fname_src->st.st_ex_size = 0;
6622 /* Do the actual copy. */
6623 if (smb_fname_src->st.st_ex_size) {
6624 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6627 close_file(NULL, fsp1, NORMAL_CLOSE);
6629 /* Ensure the modtime is set correctly on the destination file. */
6630 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6633 * As we are opening fsp1 read-only we only expect
6634 * an error on close on fsp2 if we are out of space.
6635 * Thus we don't look at the error return from the
6638 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6640 if (!NT_STATUS_IS_OK(status)) {
6644 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6645 status = NT_STATUS_DISK_FULL;
6649 status = NT_STATUS_OK;
6652 TALLOC_FREE(smb_fname_dst_tmp);
6656 /****************************************************************************
6657 Reply to a file copy.
6658 ****************************************************************************/
6660 void reply_copy(struct smb_request *req)
6662 connection_struct *conn = req->conn;
6663 struct smb_filename *smb_fname_src = NULL;
6664 struct smb_filename *smb_fname_dst = NULL;
6665 char *fname_src = NULL;
6666 char *fname_dst = NULL;
6667 char *fname_src_mask = NULL;
6668 char *fname_src_dir = NULL;
6671 int error = ERRnoaccess;
6675 bool target_is_directory=False;
6676 bool source_has_wild = False;
6677 bool dest_has_wild = False;
6679 TALLOC_CTX *ctx = talloc_tos();
6681 START_PROFILE(SMBcopy);
6684 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6688 tid2 = SVAL(req->vwv+0, 0);
6689 ofun = SVAL(req->vwv+1, 0);
6690 flags = SVAL(req->vwv+2, 0);
6692 p = (const char *)req->buf;
6693 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6694 &status, &source_has_wild);
6695 if (!NT_STATUS_IS_OK(status)) {
6696 reply_nterror(req, status);
6699 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6700 &status, &dest_has_wild);
6701 if (!NT_STATUS_IS_OK(status)) {
6702 reply_nterror(req, status);
6706 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6708 if (tid2 != conn->cnum) {
6709 /* can't currently handle inter share copies XXXX */
6710 DEBUG(3,("Rejecting inter-share copy\n"));
6711 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6715 status = filename_convert(ctx, conn,
6716 req->flags2 & FLAGS2_DFS_PATHNAMES,
6718 UCF_COND_ALLOW_WCARD_LCOMP,
6721 if (!NT_STATUS_IS_OK(status)) {
6722 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6723 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6724 ERRSRV, ERRbadpath);
6727 reply_nterror(req, status);
6731 status = filename_convert(ctx, conn,
6732 req->flags2 & FLAGS2_DFS_PATHNAMES,
6734 UCF_COND_ALLOW_WCARD_LCOMP,
6737 if (!NT_STATUS_IS_OK(status)) {
6738 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6739 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6740 ERRSRV, ERRbadpath);
6743 reply_nterror(req, status);
6747 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6749 if ((flags&1) && target_is_directory) {
6750 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6754 if ((flags&2) && !target_is_directory) {
6755 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6759 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6760 /* wants a tree copy! XXXX */
6761 DEBUG(3,("Rejecting tree copy\n"));
6762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6766 /* Split up the directory from the filename/mask. */
6767 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6768 &fname_src_dir, &fname_src_mask);
6769 if (!NT_STATUS_IS_OK(status)) {
6770 reply_nterror(req, NT_STATUS_NO_MEMORY);
6775 * We should only check the mangled cache
6776 * here if unix_convert failed. This means
6777 * that the path in 'mask' doesn't exist
6778 * on the file system and so we need to look
6779 * for a possible mangle. This patch from
6780 * Tine Smukavec <valentin.smukavec@hermes.si>.
6782 if (!VALID_STAT(smb_fname_src->st) &&
6783 mangle_is_mangled(fname_src_mask, conn->params)) {
6784 char *new_mask = NULL;
6785 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6786 &new_mask, conn->params);
6788 /* Use demangled name if one was successfully found. */
6790 TALLOC_FREE(fname_src_mask);
6791 fname_src_mask = new_mask;
6795 if (!source_has_wild) {
6798 * Only one file needs to be copied. Append the mask back onto
6801 TALLOC_FREE(smb_fname_src->base_name);
6802 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6806 if (!smb_fname_src->base_name) {
6807 reply_nterror(req, NT_STATUS_NO_MEMORY);
6811 if (dest_has_wild) {
6812 char *fname_dst_mod = NULL;
6813 if (!resolve_wildcards(smb_fname_dst,
6814 smb_fname_src->base_name,
6815 smb_fname_dst->base_name,
6817 reply_nterror(req, NT_STATUS_NO_MEMORY);
6820 TALLOC_FREE(smb_fname_dst->base_name);
6821 smb_fname_dst->base_name = fname_dst_mod;
6824 status = check_name(conn, smb_fname_src->base_name);
6825 if (!NT_STATUS_IS_OK(status)) {
6826 reply_nterror(req, status);
6830 status = check_name(conn, smb_fname_dst->base_name);
6831 if (!NT_STATUS_IS_OK(status)) {
6832 reply_nterror(req, status);
6836 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6837 ofun, count, target_is_directory);
6839 if(!NT_STATUS_IS_OK(status)) {
6840 reply_nterror(req, status);
6846 struct smb_Dir *dir_hnd = NULL;
6847 const char *dname = NULL;
6848 char *talloced = NULL;
6852 * There is a wildcard that requires us to actually read the
6853 * src dir and copy each file matching the mask to the dst.
6854 * Right now streams won't be copied, but this could
6855 * presumably be added with a nested loop for reach dir entry.
6857 SMB_ASSERT(!smb_fname_src->stream_name);
6858 SMB_ASSERT(!smb_fname_dst->stream_name);
6860 smb_fname_src->stream_name = NULL;
6861 smb_fname_dst->stream_name = NULL;
6863 if (strequal(fname_src_mask,"????????.???")) {
6864 TALLOC_FREE(fname_src_mask);
6865 fname_src_mask = talloc_strdup(ctx, "*");
6866 if (!fname_src_mask) {
6867 reply_nterror(req, NT_STATUS_NO_MEMORY);
6872 status = check_name(conn, fname_src_dir);
6873 if (!NT_STATUS_IS_OK(status)) {
6874 reply_nterror(req, status);
6878 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6879 if (dir_hnd == NULL) {
6880 status = map_nt_error_from_unix(errno);
6881 reply_nterror(req, status);
6887 /* Iterate over the src dir copying each entry to the dst. */
6888 while ((dname = ReadDirName(dir_hnd, &offset,
6889 &smb_fname_src->st, &talloced))) {
6890 char *destname = NULL;
6892 if (ISDOT(dname) || ISDOTDOT(dname)) {
6893 TALLOC_FREE(talloced);
6897 if (!is_visible_file(conn, fname_src_dir, dname,
6898 &smb_fname_src->st, false)) {
6899 TALLOC_FREE(talloced);
6903 if(!mask_match(dname, fname_src_mask,
6904 conn->case_sensitive)) {
6905 TALLOC_FREE(talloced);
6909 error = ERRnoaccess;
6911 /* Get the src smb_fname struct setup. */
6912 TALLOC_FREE(smb_fname_src->base_name);
6913 smb_fname_src->base_name =
6914 talloc_asprintf(smb_fname_src, "%s/%s",
6915 fname_src_dir, dname);
6917 if (!smb_fname_src->base_name) {
6918 TALLOC_FREE(dir_hnd);
6919 TALLOC_FREE(talloced);
6920 reply_nterror(req, NT_STATUS_NO_MEMORY);
6924 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6925 smb_fname_dst->base_name,
6927 TALLOC_FREE(talloced);
6931 TALLOC_FREE(dir_hnd);
6932 TALLOC_FREE(talloced);
6933 reply_nterror(req, NT_STATUS_NO_MEMORY);
6937 TALLOC_FREE(smb_fname_dst->base_name);
6938 smb_fname_dst->base_name = destname;
6940 status = check_name(conn, smb_fname_src->base_name);
6941 if (!NT_STATUS_IS_OK(status)) {
6942 TALLOC_FREE(dir_hnd);
6943 TALLOC_FREE(talloced);
6944 reply_nterror(req, status);
6948 status = check_name(conn, smb_fname_dst->base_name);
6949 if (!NT_STATUS_IS_OK(status)) {
6950 TALLOC_FREE(dir_hnd);
6951 TALLOC_FREE(talloced);
6952 reply_nterror(req, status);
6956 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
6957 smb_fname_src->base_name,
6958 smb_fname_dst->base_name));
6960 status = copy_file(ctx, conn, smb_fname_src,
6961 smb_fname_dst, ofun, count,
6962 target_is_directory);
6963 if (NT_STATUS_IS_OK(status)) {
6967 TALLOC_FREE(talloced);
6969 TALLOC_FREE(dir_hnd);
6973 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
6977 reply_outbuf(req, 1, 0);
6978 SSVAL(req->outbuf,smb_vwv0,count);
6980 TALLOC_FREE(smb_fname_src);
6981 TALLOC_FREE(smb_fname_dst);
6982 TALLOC_FREE(fname_src);
6983 TALLOC_FREE(fname_dst);
6984 TALLOC_FREE(fname_src_mask);
6985 TALLOC_FREE(fname_src_dir);
6987 END_PROFILE(SMBcopy);
6992 #define DBGC_CLASS DBGC_LOCKING
6994 /****************************************************************************
6995 Get a lock pid, dealing with large count requests.
6996 ****************************************************************************/
6998 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
6999 bool large_file_format)
7001 if(!large_file_format)
7002 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7004 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7007 /****************************************************************************
7008 Get a lock count, dealing with large count requests.
7009 ****************************************************************************/
7011 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7012 bool large_file_format)
7016 if(!large_file_format) {
7017 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7020 #if defined(HAVE_LONGLONG)
7021 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7022 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7023 #else /* HAVE_LONGLONG */
7026 * NT4.x seems to be broken in that it sends large file (64 bit)
7027 * lockingX calls even if the CAP_LARGE_FILES was *not*
7028 * negotiated. For boxes without large unsigned ints truncate the
7029 * lock count by dropping the top 32 bits.
7032 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7033 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7034 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7035 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7036 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7039 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7040 #endif /* HAVE_LONGLONG */
7046 #if !defined(HAVE_LONGLONG)
7047 /****************************************************************************
7048 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7049 ****************************************************************************/
7051 static uint32 map_lock_offset(uint32 high, uint32 low)
7055 uint32 highcopy = high;
7058 * Try and find out how many significant bits there are in high.
7061 for(i = 0; highcopy; i++)
7065 * We use 31 bits not 32 here as POSIX
7066 * lock offsets may not be negative.
7069 mask = (~0) << (31 - i);
7072 return 0; /* Fail. */
7078 #endif /* !defined(HAVE_LONGLONG) */
7080 /****************************************************************************
7081 Get a lock offset, dealing with large offset requests.
7082 ****************************************************************************/
7084 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7085 bool large_file_format, bool *err)
7087 uint64_t offset = 0;
7091 if(!large_file_format) {
7092 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7095 #if defined(HAVE_LONGLONG)
7096 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7097 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7098 #else /* HAVE_LONGLONG */
7101 * NT4.x seems to be broken in that it sends large file (64 bit)
7102 * lockingX calls even if the CAP_LARGE_FILES was *not*
7103 * negotiated. For boxes without large unsigned ints mangle the
7104 * lock offset by mapping the top 32 bits onto the lower 32.
7107 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7108 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7109 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7112 if((new_low = map_lock_offset(high, low)) == 0) {
7114 return (uint64_t)-1;
7117 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7118 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7119 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7120 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7123 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7124 #endif /* HAVE_LONGLONG */
7130 NTSTATUS smbd_do_locking(struct smb_request *req,
7134 uint16_t num_ulocks,
7135 struct smbd_lock_element *ulocks,
7137 struct smbd_lock_element *locks,
7140 connection_struct *conn = req->conn;
7142 NTSTATUS status = NT_STATUS_OK;
7146 /* Data now points at the beginning of the list
7147 of smb_unlkrng structs */
7148 for(i = 0; i < (int)num_ulocks; i++) {
7149 struct smbd_lock_element *e = &ulocks[i];
7151 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7152 "pid %u, file %s\n",
7155 (unsigned int)e->smblctx,
7158 if (e->brltype != UNLOCK_LOCK) {
7159 /* this can only happen with SMB2 */
7160 return NT_STATUS_INVALID_PARAMETER;
7163 status = do_unlock(req->sconn->msg_ctx,
7170 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7171 nt_errstr(status)));
7173 if (!NT_STATUS_IS_OK(status)) {
7178 /* Setup the timeout in seconds. */
7180 if (!lp_blocking_locks(SNUM(conn))) {
7184 /* Data now points at the beginning of the list
7185 of smb_lkrng structs */
7187 for(i = 0; i < (int)num_locks; i++) {
7188 struct smbd_lock_element *e = &locks[i];
7190 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7191 "%llu, file %s timeout = %d\n",
7194 (unsigned long long)e->smblctx,
7198 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7199 struct blocking_lock_record *blr = NULL;
7201 if (num_locks > 1) {
7203 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7204 * if the lock vector contains one entry. When given mutliple cancel
7205 * requests in a single PDU we expect the server to return an
7206 * error. Windows servers seem to accept the request but only
7207 * cancel the first lock.
7208 * JRA - Do what Windows does (tm) :-).
7212 /* MS-CIFS (2.2.4.32.1) behavior. */
7213 return NT_STATUS_DOS(ERRDOS,
7214 ERRcancelviolation);
7216 /* Windows behavior. */
7218 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7219 "cancel request\n"));
7225 if (lp_blocking_locks(SNUM(conn))) {
7227 /* Schedule a message to ourselves to
7228 remove the blocking lock record and
7229 return the right error. */
7231 blr = blocking_lock_cancel_smb1(fsp,
7237 NT_STATUS_FILE_LOCK_CONFLICT);
7239 return NT_STATUS_DOS(
7241 ERRcancelviolation);
7244 /* Remove a matching pending lock. */
7245 status = do_lock_cancel(fsp,
7252 bool blocking_lock = timeout ? true : false;
7253 bool defer_lock = false;
7254 struct byte_range_lock *br_lck;
7255 uint64_t block_smblctx;
7257 br_lck = do_lock(req->sconn->msg_ctx,
7269 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7270 /* Windows internal resolution for blocking locks seems
7271 to be about 200ms... Don't wait for less than that. JRA. */
7272 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7273 timeout = lp_lock_spin_time();
7278 /* If a lock sent with timeout of zero would fail, and
7279 * this lock has been requested multiple times,
7280 * according to brl_lock_failed() we convert this
7281 * request to a blocking lock with a timeout of between
7282 * 150 - 300 milliseconds.
7284 * If lp_lock_spin_time() has been set to 0, we skip
7285 * this blocking retry and fail immediately.
7287 * Replacement for do_lock_spin(). JRA. */
7289 if (!req->sconn->using_smb2 &&
7290 br_lck && lp_blocking_locks(SNUM(conn)) &&
7291 lp_lock_spin_time() && !blocking_lock &&
7292 NT_STATUS_EQUAL((status),
7293 NT_STATUS_FILE_LOCK_CONFLICT))
7296 timeout = lp_lock_spin_time();
7299 if (br_lck && defer_lock) {
7301 * A blocking lock was requested. Package up
7302 * this smb into a queued request and push it
7303 * onto the blocking lock queue.
7305 if(push_blocking_lock_request(br_lck,
7316 TALLOC_FREE(br_lck);
7318 return NT_STATUS_OK;
7322 TALLOC_FREE(br_lck);
7325 if (!NT_STATUS_IS_OK(status)) {
7330 /* If any of the above locks failed, then we must unlock
7331 all of the previous locks (X/Open spec). */
7333 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7335 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7336 i = -1; /* we want to skip the for loop */
7340 * Ensure we don't do a remove on the lock that just failed,
7341 * as under POSIX rules, if we have a lock already there, we
7342 * will delete it (and we shouldn't) .....
7344 for(i--; i >= 0; i--) {
7345 struct smbd_lock_element *e = &locks[i];
7347 do_unlock(req->sconn->msg_ctx,
7357 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7358 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7360 return NT_STATUS_OK;
7363 /****************************************************************************
7364 Reply to a lockingX request.
7365 ****************************************************************************/
7367 void reply_lockingX(struct smb_request *req)
7369 connection_struct *conn = req->conn;
7371 unsigned char locktype;
7372 unsigned char oplocklevel;
7377 const uint8_t *data;
7378 bool large_file_format;
7380 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7381 struct smbd_lock_element *ulocks;
7382 struct smbd_lock_element *locks;
7385 START_PROFILE(SMBlockingX);
7388 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7389 END_PROFILE(SMBlockingX);
7393 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7394 locktype = CVAL(req->vwv+3, 0);
7395 oplocklevel = CVAL(req->vwv+3, 1);
7396 num_ulocks = SVAL(req->vwv+6, 0);
7397 num_locks = SVAL(req->vwv+7, 0);
7398 lock_timeout = IVAL(req->vwv+4, 0);
7399 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7401 if (!check_fsp(conn, req, fsp)) {
7402 END_PROFILE(SMBlockingX);
7408 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7409 /* we don't support these - and CANCEL_LOCK makes w2k
7410 and XP reboot so I don't really want to be
7411 compatible! (tridge) */
7412 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7413 END_PROFILE(SMBlockingX);
7417 /* Check if this is an oplock break on a file
7418 we have granted an oplock on.
7420 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7421 /* Client can insist on breaking to none. */
7422 bool break_to_none = (oplocklevel == 0);
7425 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7426 "for fnum = %d\n", (unsigned int)oplocklevel,
7430 * Make sure we have granted an exclusive or batch oplock on
7434 if (fsp->oplock_type == 0) {
7436 /* The Samba4 nbench simulator doesn't understand
7437 the difference between break to level2 and break
7438 to none from level2 - it sends oplock break
7439 replies in both cases. Don't keep logging an error
7440 message here - just ignore it. JRA. */
7442 DEBUG(5,("reply_lockingX: Error : oplock break from "
7443 "client for fnum = %d (oplock=%d) and no "
7444 "oplock granted on this file (%s).\n",
7445 fsp->fnum, fsp->oplock_type,
7448 /* if this is a pure oplock break request then don't
7450 if (num_locks == 0 && num_ulocks == 0) {
7451 END_PROFILE(SMBlockingX);
7454 END_PROFILE(SMBlockingX);
7455 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7460 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7462 result = remove_oplock(fsp);
7464 result = downgrade_oplock(fsp);
7468 DEBUG(0, ("reply_lockingX: error in removing "
7469 "oplock on file %s\n", fsp_str_dbg(fsp)));
7470 /* Hmmm. Is this panic justified? */
7471 smb_panic("internal tdb error");
7474 reply_to_oplock_break_requests(fsp);
7476 /* if this is a pure oplock break request then don't send a
7478 if (num_locks == 0 && num_ulocks == 0) {
7479 /* Sanity check - ensure a pure oplock break is not a
7481 if(CVAL(req->vwv+0, 0) != 0xff)
7482 DEBUG(0,("reply_lockingX: Error : pure oplock "
7483 "break is a chained %d request !\n",
7484 (unsigned int)CVAL(req->vwv+0, 0)));
7485 END_PROFILE(SMBlockingX);
7491 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7492 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7493 END_PROFILE(SMBlockingX);
7497 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7498 if (ulocks == NULL) {
7499 reply_nterror(req, NT_STATUS_NO_MEMORY);
7500 END_PROFILE(SMBlockingX);
7504 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7505 if (locks == NULL) {
7506 reply_nterror(req, NT_STATUS_NO_MEMORY);
7507 END_PROFILE(SMBlockingX);
7511 /* Data now points at the beginning of the list
7512 of smb_unlkrng structs */
7513 for(i = 0; i < (int)num_ulocks; i++) {
7514 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7515 ulocks[i].count = get_lock_count(data, i, large_file_format);
7516 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7517 ulocks[i].brltype = UNLOCK_LOCK;
7520 * There is no error code marked "stupid client bug".... :-).
7523 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7524 END_PROFILE(SMBlockingX);
7529 /* Now do any requested locks */
7530 data += ((large_file_format ? 20 : 10)*num_ulocks);
7532 /* Data now points at the beginning of the list
7533 of smb_lkrng structs */
7535 for(i = 0; i < (int)num_locks; i++) {
7536 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7537 locks[i].count = get_lock_count(data, i, large_file_format);
7538 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7540 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7541 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7542 locks[i].brltype = PENDING_READ_LOCK;
7544 locks[i].brltype = READ_LOCK;
7547 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7548 locks[i].brltype = PENDING_WRITE_LOCK;
7550 locks[i].brltype = WRITE_LOCK;
7555 * There is no error code marked "stupid client bug".... :-).
7558 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7559 END_PROFILE(SMBlockingX);
7564 status = smbd_do_locking(req, fsp,
7565 locktype, lock_timeout,
7569 if (!NT_STATUS_IS_OK(status)) {
7570 END_PROFILE(SMBlockingX);
7571 reply_nterror(req, status);
7575 END_PROFILE(SMBlockingX);
7579 reply_outbuf(req, 2, 0);
7581 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7582 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7584 END_PROFILE(SMBlockingX);
7589 #define DBGC_CLASS DBGC_ALL
7591 /****************************************************************************
7592 Reply to a SMBreadbmpx (read block multiplex) request.
7593 Always reply with an error, if someone has a platform really needs this,
7594 please contact vl@samba.org
7595 ****************************************************************************/
7597 void reply_readbmpx(struct smb_request *req)
7599 START_PROFILE(SMBreadBmpx);
7600 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7601 END_PROFILE(SMBreadBmpx);
7605 /****************************************************************************
7606 Reply to a SMBreadbs (read block multiplex secondary) request.
7607 Always reply with an error, if someone has a platform really needs this,
7608 please contact vl@samba.org
7609 ****************************************************************************/
7611 void reply_readbs(struct smb_request *req)
7613 START_PROFILE(SMBreadBs);
7614 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7615 END_PROFILE(SMBreadBs);
7619 /****************************************************************************
7620 Reply to a SMBsetattrE.
7621 ****************************************************************************/
7623 void reply_setattrE(struct smb_request *req)
7625 connection_struct *conn = req->conn;
7626 struct smb_file_time ft;
7630 START_PROFILE(SMBsetattrE);
7634 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7638 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7640 if(!fsp || (fsp->conn != conn)) {
7641 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7646 * Convert the DOS times into unix times.
7649 ft.atime = convert_time_t_to_timespec(
7650 srv_make_unix_date2(req->vwv+3));
7651 ft.mtime = convert_time_t_to_timespec(
7652 srv_make_unix_date2(req->vwv+5));
7653 ft.create_time = convert_time_t_to_timespec(
7654 srv_make_unix_date2(req->vwv+1));
7656 reply_outbuf(req, 0, 0);
7659 * Patch from Ray Frush <frush@engr.colostate.edu>
7660 * Sometimes times are sent as zero - ignore them.
7663 /* Ensure we have a valid stat struct for the source. */
7664 status = vfs_stat_fsp(fsp);
7665 if (!NT_STATUS_IS_OK(status)) {
7666 reply_nterror(req, status);
7670 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7671 if (!NT_STATUS_IS_OK(status)) {
7672 reply_nterror(req, status);
7676 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7679 (unsigned int)ft.atime.tv_sec,
7680 (unsigned int)ft.mtime.tv_sec,
7681 (unsigned int)ft.create_time.tv_sec
7684 END_PROFILE(SMBsetattrE);
7689 /* Back from the dead for OS/2..... JRA. */
7691 /****************************************************************************
7692 Reply to a SMBwritebmpx (write block multiplex primary) request.
7693 Always reply with an error, if someone has a platform really needs this,
7694 please contact vl@samba.org
7695 ****************************************************************************/
7697 void reply_writebmpx(struct smb_request *req)
7699 START_PROFILE(SMBwriteBmpx);
7700 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7701 END_PROFILE(SMBwriteBmpx);
7705 /****************************************************************************
7706 Reply to a SMBwritebs (write block multiplex secondary) request.
7707 Always reply with an error, if someone has a platform really needs this,
7708 please contact vl@samba.org
7709 ****************************************************************************/
7711 void reply_writebs(struct smb_request *req)
7713 START_PROFILE(SMBwriteBs);
7714 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7715 END_PROFILE(SMBwriteBs);
7719 /****************************************************************************
7720 Reply to a SMBgetattrE.
7721 ****************************************************************************/
7723 void reply_getattrE(struct smb_request *req)
7725 connection_struct *conn = req->conn;
7728 struct timespec create_ts;
7730 START_PROFILE(SMBgetattrE);
7733 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7734 END_PROFILE(SMBgetattrE);
7738 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7740 if(!fsp || (fsp->conn != conn)) {
7741 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7742 END_PROFILE(SMBgetattrE);
7746 /* Do an fstat on this file */
7748 reply_nterror(req, map_nt_error_from_unix(errno));
7749 END_PROFILE(SMBgetattrE);
7753 mode = dos_mode(conn, fsp->fsp_name);
7756 * Convert the times into dos times. Set create
7757 * date to be last modify date as UNIX doesn't save
7761 reply_outbuf(req, 11, 0);
7763 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7764 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7765 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7766 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7767 /* Should we check pending modtime here ? JRA */
7768 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7769 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7772 SIVAL(req->outbuf, smb_vwv6, 0);
7773 SIVAL(req->outbuf, smb_vwv8, 0);
7775 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7776 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7777 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7779 SSVAL(req->outbuf,smb_vwv10, mode);
7781 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7783 END_PROFILE(SMBgetattrE);