2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "smbd/globals.h"
30 extern enum protocol_types Protocol;
32 /****************************************************************************
33 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
34 path or anything including wildcards.
35 We're assuming here that '/' is not the second byte in any multibyte char
36 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
38 ****************************************************************************/
40 /* Custom version for processing POSIX paths. */
41 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
43 static NTSTATUS check_path_syntax_internal(char *path,
45 bool *p_last_component_contains_wcard)
49 NTSTATUS ret = NT_STATUS_OK;
50 bool start_of_name_component = True;
51 bool stream_started = false;
53 *p_last_component_contains_wcard = False;
60 return NT_STATUS_OBJECT_NAME_INVALID;
63 return NT_STATUS_OBJECT_NAME_INVALID;
65 if (strchr_m(&s[1], ':')) {
66 return NT_STATUS_OBJECT_NAME_INVALID;
68 if (StrCaseCmp(s, ":$DATA") != 0) {
69 return NT_STATUS_INVALID_PARAMETER;
75 if (!stream_started && *s == ':') {
76 if (*p_last_component_contains_wcard) {
77 return NT_STATUS_OBJECT_NAME_INVALID;
79 /* stream names allow more characters than file names */
80 stream_started = true;
81 start_of_name_component = false;
85 return NT_STATUS_OBJECT_NAME_INVALID;
89 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
91 * Safe to assume is not the second part of a mb char
92 * as this is handled below.
94 /* Eat multiple '/' or '\\' */
95 while (IS_PATH_SEP(*s,posix_path)) {
98 if ((d != path) && (*s != '\0')) {
99 /* We only care about non-leading or trailing '/' or '\\' */
103 start_of_name_component = True;
105 *p_last_component_contains_wcard = False;
109 if (start_of_name_component) {
110 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
111 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
114 * No mb char starts with '.' so we're safe checking the directory separator here.
117 /* If we just added a '/' - delete it */
118 if ((d > path) && (*(d-1) == '/')) {
123 /* Are we at the start ? Can't go back further if so. */
125 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
128 /* Go back one level... */
129 /* We know this is safe as '/' cannot be part of a mb sequence. */
130 /* NOTE - if this assumption is invalid we are not in good shape... */
131 /* Decrement d first as d points to the *next* char to write into. */
132 for (d--; d > path; d--) {
136 s += 2; /* Else go past the .. */
137 /* We're still at the start of a name component, just the previous one. */
140 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
152 if (*s <= 0x1f || *s == '|') {
153 return NT_STATUS_OBJECT_NAME_INVALID;
161 *p_last_component_contains_wcard = True;
170 /* Get the size of the next MB character. */
171 next_codepoint(s,&siz);
189 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
191 return NT_STATUS_INVALID_PARAMETER;
194 start_of_name_component = False;
202 /****************************************************************************
203 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
204 No wildcards allowed.
205 ****************************************************************************/
207 NTSTATUS check_path_syntax(char *path)
210 return check_path_syntax_internal(path, False, &ignore);
213 /****************************************************************************
214 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
215 Wildcards allowed - p_contains_wcard returns true if the last component contained
217 ****************************************************************************/
219 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
221 return check_path_syntax_internal(path, False, p_contains_wcard);
224 /****************************************************************************
225 Check the path for a POSIX client.
226 We're assuming here that '/' is not the second byte in any multibyte char
227 set (a safe assumption).
228 ****************************************************************************/
230 NTSTATUS check_path_syntax_posix(char *path)
233 return check_path_syntax_internal(path, True, &ignore);
236 /****************************************************************************
237 Pull a string and check the path allowing a wilcard - provide for error return.
238 ****************************************************************************/
240 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
241 const char *base_ptr,
248 bool *contains_wcard)
254 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
258 *err = NT_STATUS_INVALID_PARAMETER;
262 *contains_wcard = False;
264 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
266 * For a DFS path the function parse_dfs_path()
267 * will do the path processing, just make a copy.
273 if (lp_posix_pathnames()) {
274 *err = check_path_syntax_posix(*pp_dest);
276 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
282 /****************************************************************************
283 Pull a string and check the path - provide for error return.
284 ****************************************************************************/
286 size_t srvstr_get_path(TALLOC_CTX *ctx,
287 const char *base_ptr,
296 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
297 src_len, flags, err, &ignore);
300 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
301 char **pp_dest, const char *src, int flags,
302 NTSTATUS *err, bool *contains_wcard)
304 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
305 pp_dest, src, smbreq_bufrem(req, src),
306 flags, err, contains_wcard);
309 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
310 char **pp_dest, const char *src, int flags,
314 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
315 flags, err, &ignore);
318 /****************************************************************************
319 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
320 ****************************************************************************/
322 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
325 if (!(fsp) || !(conn)) {
326 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
329 if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
330 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
336 /****************************************************************************
337 Check if we have a correct fsp pointing to a file.
338 ****************************************************************************/
340 bool check_fsp(connection_struct *conn, struct smb_request *req,
343 if (!check_fsp_open(conn, req, fsp)) {
346 if ((fsp)->is_directory) {
347 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
350 if ((fsp)->fh->fd == -1) {
351 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
354 (fsp)->num_smb_operations++;
358 /****************************************************************************
359 Check if we have a correct fsp pointing to a quota fake file. Replacement for
360 the CHECK_NTQUOTA_HANDLE_OK macro.
361 ****************************************************************************/
363 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
366 if (!check_fsp_open(conn, req, fsp)) {
370 if (fsp->is_directory) {
374 if (fsp->fake_file_handle == NULL) {
378 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
382 if (fsp->fake_file_handle->private_data == NULL) {
389 /****************************************************************************
390 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
391 ****************************************************************************/
393 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
396 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
397 && (req->vuid == (fsp)->vuid)) {
401 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
405 /****************************************************************************
406 Reply to a (netbios-level) special message.
407 ****************************************************************************/
409 void reply_special(char *inbuf)
411 int msg_type = CVAL(inbuf,0);
412 int msg_flags = CVAL(inbuf,1);
417 * We only really use 4 bytes of the outbuf, but for the smb_setlen
418 * calculation & friends (srv_send_smb uses that) we need the full smb
421 char outbuf[smb_size];
425 memset(outbuf, '\0', sizeof(outbuf));
427 smb_setlen(outbuf,0);
430 case 0x81: /* session request */
432 if (already_got_session) {
433 exit_server_cleanly("multiple session request not permitted");
436 SCVAL(outbuf,0,0x82);
438 if (name_len(inbuf+4) > 50 ||
439 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
440 DEBUG(0,("Invalid name length in session request\n"));
443 name_extract(inbuf,4,name1);
444 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
445 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
448 set_local_machine_name(name1, True);
449 set_remote_machine_name(name2, True);
451 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
452 get_local_machine_name(), get_remote_machine_name(),
455 if (name_type == 'R') {
456 /* We are being asked for a pathworks session ---
458 SCVAL(outbuf, 0,0x83);
462 /* only add the client's machine name to the list
463 of possibly valid usernames if we are operating
464 in share mode security */
465 if (lp_security() == SEC_SHARE) {
466 add_session_user(get_remote_machine_name());
469 reload_services(True);
472 already_got_session = True;
475 case 0x89: /* session keepalive request
476 (some old clients produce this?) */
477 SCVAL(outbuf,0,SMBkeepalive);
481 case 0x82: /* positive session response */
482 case 0x83: /* negative session response */
483 case 0x84: /* retarget session response */
484 DEBUG(0,("Unexpected session response\n"));
487 case SMBkeepalive: /* session keepalive */
492 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
493 msg_type, msg_flags));
495 srv_send_smb(smbd_server_fd(), outbuf, false, NULL);
499 /****************************************************************************
501 conn POINTER CAN BE NULL HERE !
502 ****************************************************************************/
504 void reply_tcon(struct smb_request *req)
506 connection_struct *conn = req->conn;
508 char *service_buf = NULL;
509 char *password = NULL;
514 DATA_BLOB password_blob;
515 TALLOC_CTX *ctx = talloc_tos();
517 START_PROFILE(SMBtcon);
519 if (req->buflen < 4) {
520 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
521 END_PROFILE(SMBtcon);
525 p = (const char *)req->buf + 1;
526 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
528 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
530 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
533 if (service_buf == NULL || password == NULL || dev == NULL) {
534 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
535 END_PROFILE(SMBtcon);
538 p = strrchr_m(service_buf,'\\');
542 service = service_buf;
545 password_blob = data_blob(password, pwlen+1);
547 conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
550 data_blob_clear_free(&password_blob);
553 reply_nterror(req, nt_status);
554 END_PROFILE(SMBtcon);
558 reply_outbuf(req, 2, 0);
559 SSVAL(req->outbuf,smb_vwv0,max_recv);
560 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
561 SSVAL(req->outbuf,smb_tid,conn->cnum);
563 DEBUG(3,("tcon service=%s cnum=%d\n",
564 service, conn->cnum));
566 END_PROFILE(SMBtcon);
570 /****************************************************************************
571 Reply to a tcon and X.
572 conn POINTER CAN BE NULL HERE !
573 ****************************************************************************/
575 void reply_tcon_and_X(struct smb_request *req)
577 connection_struct *conn = req->conn;
578 const char *service = NULL;
580 TALLOC_CTX *ctx = talloc_tos();
581 /* what the cleint thinks the device is */
582 char *client_devicetype = NULL;
583 /* what the server tells the client the share represents */
584 const char *server_devicetype;
591 START_PROFILE(SMBtconX);
594 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
595 END_PROFILE(SMBtconX);
599 passlen = SVAL(req->vwv+3, 0);
600 tcon_flags = SVAL(req->vwv+2, 0);
602 /* we might have to close an old one */
603 if ((tcon_flags & 0x1) && conn) {
604 close_cnum(conn,req->vuid);
609 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
610 reply_doserror(req, ERRDOS, ERRbuftoosmall);
611 END_PROFILE(SMBtconX);
615 if (global_encrypted_passwords_negotiated) {
616 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
617 if (lp_security() == SEC_SHARE) {
619 * Security = share always has a pad byte
620 * after the password.
622 p = (const char *)req->buf + passlen + 1;
624 p = (const char *)req->buf + passlen;
627 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
628 /* Ensure correct termination */
629 password.data[passlen]=0;
630 p = (const char *)req->buf + passlen + 1;
633 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
636 data_blob_clear_free(&password);
637 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
638 END_PROFILE(SMBtconX);
643 * the service name can be either: \\server\share
644 * or share directly like on the DELL PowerVault 705
647 q = strchr_m(path+2,'\\');
649 data_blob_clear_free(&password);
650 reply_doserror(req, ERRDOS, ERRnosuchshare);
651 END_PROFILE(SMBtconX);
659 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
660 &client_devicetype, p,
661 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
663 if (client_devicetype == NULL) {
664 data_blob_clear_free(&password);
665 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
666 END_PROFILE(SMBtconX);
670 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
672 conn = make_connection(service, password, client_devicetype,
673 req->vuid, &nt_status);
676 data_blob_clear_free(&password);
679 reply_nterror(req, nt_status);
680 END_PROFILE(SMBtconX);
685 server_devicetype = "IPC";
686 else if ( IS_PRINT(conn) )
687 server_devicetype = "LPT1:";
689 server_devicetype = "A:";
691 if (Protocol < PROTOCOL_NT1) {
692 reply_outbuf(req, 2, 0);
693 if (message_push_string(&req->outbuf, server_devicetype,
694 STR_TERMINATE|STR_ASCII) == -1) {
695 reply_nterror(req, NT_STATUS_NO_MEMORY);
696 END_PROFILE(SMBtconX);
700 /* NT sets the fstype of IPC$ to the null string */
701 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
703 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
704 /* Return permissions. */
708 reply_outbuf(req, 7, 0);
711 perm1 = FILE_ALL_ACCESS;
712 perm2 = FILE_ALL_ACCESS;
714 perm1 = CAN_WRITE(conn) ?
719 SIVAL(req->outbuf, smb_vwv3, perm1);
720 SIVAL(req->outbuf, smb_vwv5, perm2);
722 reply_outbuf(req, 3, 0);
725 if ((message_push_string(&req->outbuf, server_devicetype,
726 STR_TERMINATE|STR_ASCII) == -1)
727 || (message_push_string(&req->outbuf, fstype,
728 STR_TERMINATE) == -1)) {
729 reply_nterror(req, NT_STATUS_NO_MEMORY);
730 END_PROFILE(SMBtconX);
734 /* what does setting this bit do? It is set by NT4 and
735 may affect the ability to autorun mounted cdroms */
736 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
737 (lp_csc_policy(SNUM(conn)) << 2));
739 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
740 DEBUG(2,("Serving %s as a Dfs root\n",
741 lp_servicename(SNUM(conn)) ));
742 SSVAL(req->outbuf, smb_vwv2,
743 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
748 DEBUG(3,("tconX service=%s \n",
751 /* set the incoming and outgoing tid to the just created one */
752 SSVAL(req->inbuf,smb_tid,conn->cnum);
753 SSVAL(req->outbuf,smb_tid,conn->cnum);
755 END_PROFILE(SMBtconX);
761 /****************************************************************************
762 Reply to an unknown type.
763 ****************************************************************************/
765 void reply_unknown_new(struct smb_request *req, uint8 type)
767 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
768 smb_fn_name(type), type, type));
769 reply_doserror(req, ERRSRV, ERRunknownsmb);
773 /****************************************************************************
775 conn POINTER CAN BE NULL HERE !
776 ****************************************************************************/
778 void reply_ioctl(struct smb_request *req)
780 connection_struct *conn = req->conn;
787 START_PROFILE(SMBioctl);
790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
791 END_PROFILE(SMBioctl);
795 device = SVAL(req->vwv+1, 0);
796 function = SVAL(req->vwv+2, 0);
797 ioctl_code = (device << 16) + function;
799 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
801 switch (ioctl_code) {
802 case IOCTL_QUERY_JOB_INFO:
806 reply_doserror(req, ERRSRV, ERRnosupport);
807 END_PROFILE(SMBioctl);
811 reply_outbuf(req, 8, replysize+1);
812 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
813 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
814 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
815 p = smb_buf(req->outbuf);
816 memset(p, '\0', replysize+1); /* valgrind-safe. */
817 p += 1; /* Allow for alignment */
819 switch (ioctl_code) {
820 case IOCTL_QUERY_JOB_INFO:
822 files_struct *fsp = file_fsp(
823 req, SVAL(req->vwv+0, 0));
825 reply_doserror(req, ERRDOS, ERRbadfid);
826 END_PROFILE(SMBioctl);
829 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
830 srvstr_push((char *)req->outbuf, req->flags2, p+2,
832 STR_TERMINATE|STR_ASCII);
834 srvstr_push((char *)req->outbuf, req->flags2,
835 p+18, lp_servicename(SNUM(conn)),
836 13, STR_TERMINATE|STR_ASCII);
844 END_PROFILE(SMBioctl);
848 /****************************************************************************
849 Strange checkpath NTSTATUS mapping.
850 ****************************************************************************/
852 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
854 /* Strange DOS error code semantics only for checkpath... */
855 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
856 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
857 /* We need to map to ERRbadpath */
858 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
864 /****************************************************************************
865 Reply to a checkpath.
866 ****************************************************************************/
868 void reply_checkpath(struct smb_request *req)
870 connection_struct *conn = req->conn;
872 SMB_STRUCT_STAT sbuf;
874 TALLOC_CTX *ctx = talloc_tos();
876 START_PROFILE(SMBcheckpath);
878 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
879 STR_TERMINATE, &status);
881 if (!NT_STATUS_IS_OK(status)) {
882 status = map_checkpath_error(req->flags2, status);
883 reply_nterror(req, status);
884 END_PROFILE(SMBcheckpath);
888 status = resolve_dfspath(ctx, conn,
889 req->flags2 & FLAGS2_DFS_PATHNAMES,
892 if (!NT_STATUS_IS_OK(status)) {
893 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
894 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
896 END_PROFILE(SMBcheckpath);
902 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
904 status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf);
905 if (!NT_STATUS_IS_OK(status)) {
909 status = check_name(conn, name);
910 if (!NT_STATUS_IS_OK(status)) {
911 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
915 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
916 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
917 status = map_nt_error_from_unix(errno);
921 if (!S_ISDIR(sbuf.st_mode)) {
922 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
924 END_PROFILE(SMBcheckpath);
928 reply_outbuf(req, 0, 0);
930 END_PROFILE(SMBcheckpath);
935 END_PROFILE(SMBcheckpath);
937 /* We special case this - as when a Windows machine
938 is parsing a path is steps through the components
939 one at a time - if a component fails it expects
940 ERRbadpath, not ERRbadfile.
942 status = map_checkpath_error(req->flags2, status);
943 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
945 * Windows returns different error codes if
946 * the parent directory is valid but not the
947 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
948 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
949 * if the path is invalid.
951 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
956 reply_nterror(req, status);
959 /****************************************************************************
961 ****************************************************************************/
963 void reply_getatr(struct smb_request *req)
965 connection_struct *conn = req->conn;
967 SMB_STRUCT_STAT sbuf;
973 TALLOC_CTX *ctx = talloc_tos();
975 START_PROFILE(SMBgetatr);
977 p = (const char *)req->buf + 1;
978 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
979 if (!NT_STATUS_IS_OK(status)) {
980 reply_nterror(req, status);
981 END_PROFILE(SMBgetatr);
985 status = resolve_dfspath(ctx, conn,
986 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(SMBgetatr);
996 reply_nterror(req, status);
997 END_PROFILE(SMBgetatr);
1001 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1002 under WfWg - weird! */
1003 if (*fname == '\0') {
1004 mode = aHIDDEN | aDIR;
1005 if (!CAN_WRITE(conn)) {
1011 status = unix_convert(ctx, conn, fname, False, &fname, NULL,&sbuf);
1012 if (!NT_STATUS_IS_OK(status)) {
1013 reply_nterror(req, status);
1014 END_PROFILE(SMBgetatr);
1017 status = check_name(conn, fname);
1018 if (!NT_STATUS_IS_OK(status)) {
1019 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1020 reply_nterror(req, status);
1021 END_PROFILE(SMBgetatr);
1024 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
1025 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1026 reply_unixerror(req, ERRDOS,ERRbadfile);
1027 END_PROFILE(SMBgetatr);
1031 mode = dos_mode(conn,fname,&sbuf);
1032 size = sbuf.st_size;
1033 mtime = sbuf.st_mtime;
1039 reply_outbuf(req, 10, 0);
1041 SSVAL(req->outbuf,smb_vwv0,mode);
1042 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1043 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1045 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1047 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1049 if (Protocol >= PROTOCOL_NT1) {
1050 SSVAL(req->outbuf, smb_flg2,
1051 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1054 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1056 END_PROFILE(SMBgetatr);
1060 /****************************************************************************
1062 ****************************************************************************/
1064 void reply_setatr(struct smb_request *req)
1066 struct smb_file_time ft;
1067 connection_struct *conn = req->conn;
1071 SMB_STRUCT_STAT sbuf;
1074 TALLOC_CTX *ctx = talloc_tos();
1076 START_PROFILE(SMBsetatr);
1081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1085 p = (const char *)req->buf + 1;
1086 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1087 if (!NT_STATUS_IS_OK(status)) {
1088 reply_nterror(req, status);
1089 END_PROFILE(SMBsetatr);
1093 status = resolve_dfspath(ctx, conn,
1094 req->flags2 & FLAGS2_DFS_PATHNAMES,
1097 if (!NT_STATUS_IS_OK(status)) {
1098 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1099 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1100 ERRSRV, ERRbadpath);
1101 END_PROFILE(SMBsetatr);
1104 reply_nterror(req, status);
1105 END_PROFILE(SMBsetatr);
1109 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
1110 if (!NT_STATUS_IS_OK(status)) {
1111 reply_nterror(req, status);
1112 END_PROFILE(SMBsetatr);
1116 status = check_name(conn, fname);
1117 if (!NT_STATUS_IS_OK(status)) {
1118 reply_nterror(req, status);
1119 END_PROFILE(SMBsetatr);
1123 if (fname[0] == '.' && fname[1] == '\0') {
1125 * Not sure here is the right place to catch this
1126 * condition. Might be moved to somewhere else later -- vl
1128 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1129 END_PROFILE(SMBsetatr);
1133 mode = SVAL(req->vwv+0, 0);
1134 mtime = srv_make_unix_date3(req->vwv+1);
1136 ft.mtime = convert_time_t_to_timespec(mtime);
1137 status = smb_set_file_time(conn, NULL, fname,
1139 if (!NT_STATUS_IS_OK(status)) {
1140 reply_unixerror(req, ERRDOS, ERRnoaccess);
1141 END_PROFILE(SMBsetatr);
1145 if (mode != FILE_ATTRIBUTE_NORMAL) {
1146 if (VALID_STAT_OF_DIR(sbuf))
1151 if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) {
1152 reply_unixerror(req, ERRDOS, ERRnoaccess);
1153 END_PROFILE(SMBsetatr);
1158 reply_outbuf(req, 0, 0);
1160 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1162 END_PROFILE(SMBsetatr);
1166 /****************************************************************************
1168 ****************************************************************************/
1170 void reply_dskattr(struct smb_request *req)
1172 connection_struct *conn = req->conn;
1173 uint64_t dfree,dsize,bsize;
1174 START_PROFILE(SMBdskattr);
1176 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1177 reply_unixerror(req, ERRHRD, ERRgeneral);
1178 END_PROFILE(SMBdskattr);
1182 reply_outbuf(req, 5, 0);
1184 if (Protocol <= PROTOCOL_LANMAN2) {
1185 double total_space, free_space;
1186 /* we need to scale this to a number that DOS6 can handle. We
1187 use floating point so we can handle large drives on systems
1188 that don't have 64 bit integers
1190 we end up displaying a maximum of 2G to DOS systems
1192 total_space = dsize * (double)bsize;
1193 free_space = dfree * (double)bsize;
1195 dsize = (uint64_t)((total_space+63*512) / (64*512));
1196 dfree = (uint64_t)((free_space+63*512) / (64*512));
1198 if (dsize > 0xFFFF) dsize = 0xFFFF;
1199 if (dfree > 0xFFFF) dfree = 0xFFFF;
1201 SSVAL(req->outbuf,smb_vwv0,dsize);
1202 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1203 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1204 SSVAL(req->outbuf,smb_vwv3,dfree);
1206 SSVAL(req->outbuf,smb_vwv0,dsize);
1207 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1208 SSVAL(req->outbuf,smb_vwv2,512);
1209 SSVAL(req->outbuf,smb_vwv3,dfree);
1212 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1214 END_PROFILE(SMBdskattr);
1218 /****************************************************************************
1220 Can be called from SMBsearch, SMBffirst or SMBfunique.
1221 ****************************************************************************/
1223 void reply_search(struct smb_request *req)
1225 connection_struct *conn = req->conn;
1226 const char *mask = NULL;
1227 char *directory = NULL;
1233 unsigned int numentries = 0;
1234 unsigned int maxentries = 0;
1235 bool finished = False;
1241 bool check_descend = False;
1242 bool expect_close = False;
1244 bool mask_contains_wcard = False;
1245 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1246 TALLOC_CTX *ctx = talloc_tos();
1247 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1249 START_PROFILE(SMBsearch);
1252 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1253 END_PROFILE(SMBsearch);
1257 if (lp_posix_pathnames()) {
1258 reply_unknown_new(req, req->cmd);
1259 END_PROFILE(SMBsearch);
1263 /* If we were called as SMBffirst then we must expect close. */
1264 if(req->cmd == SMBffirst) {
1265 expect_close = True;
1268 reply_outbuf(req, 1, 3);
1269 maxentries = SVAL(req->vwv+0, 0);
1270 dirtype = SVAL(req->vwv+1, 0);
1271 p = (const char *)req->buf + 1;
1272 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1273 &nt_status, &mask_contains_wcard);
1274 if (!NT_STATUS_IS_OK(nt_status)) {
1275 reply_nterror(req, nt_status);
1276 END_PROFILE(SMBsearch);
1280 nt_status = resolve_dfspath_wcard(ctx, conn,
1281 req->flags2 & FLAGS2_DFS_PATHNAMES,
1284 &mask_contains_wcard);
1285 if (!NT_STATUS_IS_OK(nt_status)) {
1286 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1287 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1288 ERRSRV, ERRbadpath);
1289 END_PROFILE(SMBsearch);
1292 reply_nterror(req, nt_status);
1293 END_PROFILE(SMBsearch);
1298 status_len = SVAL(p, 0);
1301 /* dirtype &= ~aDIR; */
1303 if (status_len == 0) {
1304 SMB_STRUCT_STAT sbuf;
1306 nt_status = unix_convert(ctx, conn, path, True,
1307 &directory, NULL, &sbuf);
1308 if (!NT_STATUS_IS_OK(nt_status)) {
1309 reply_nterror(req, nt_status);
1310 END_PROFILE(SMBsearch);
1314 nt_status = check_name(conn, directory);
1315 if (!NT_STATUS_IS_OK(nt_status)) {
1316 reply_nterror(req, nt_status);
1317 END_PROFILE(SMBsearch);
1321 p = strrchr_m(directory,'/');
1322 if ((p != NULL) && (*directory != '/')) {
1324 directory = talloc_strndup(ctx, directory,
1325 PTR_DIFF(p, directory));
1328 directory = talloc_strdup(ctx,".");
1332 reply_nterror(req, NT_STATUS_NO_MEMORY);
1333 END_PROFILE(SMBsearch);
1337 memset((char *)status,'\0',21);
1338 SCVAL(status,0,(dirtype & 0x1F));
1340 nt_status = dptr_create(conn,
1346 mask_contains_wcard,
1349 if (!NT_STATUS_IS_OK(nt_status)) {
1350 reply_nterror(req, nt_status);
1351 END_PROFILE(SMBsearch);
1354 dptr_num = dptr_dnum(conn->dirptr);
1358 memcpy(status,p,21);
1359 status_dirtype = CVAL(status,0) & 0x1F;
1360 if (status_dirtype != (dirtype & 0x1F)) {
1361 dirtype = status_dirtype;
1364 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1365 if (!conn->dirptr) {
1368 string_set(&conn->dirpath,dptr_path(dptr_num));
1369 mask = dptr_wcard(dptr_num);
1374 * For a 'continue' search we have no string. So
1375 * check from the initial saved string.
1377 mask_contains_wcard = ms_has_wild(mask);
1378 dirtype = dptr_attr(dptr_num);
1381 DEBUG(4,("dptr_num is %d\n",dptr_num));
1383 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1384 dptr_init_search_op(conn->dirptr);
1386 if ((dirtype&0x1F) == aVOLID) {
1387 char buf[DIR_STRUCT_SIZE];
1388 memcpy(buf,status,21);
1389 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1390 0,aVOLID,0,!allow_long_path_components)) {
1391 reply_nterror(req, NT_STATUS_NO_MEMORY);
1392 END_PROFILE(SMBsearch);
1395 dptr_fill(buf+12,dptr_num);
1396 if (dptr_zero(buf+12) && (status_len==0)) {
1401 if (message_push_blob(&req->outbuf,
1402 data_blob_const(buf, sizeof(buf)))
1404 reply_nterror(req, NT_STATUS_NO_MEMORY);
1405 END_PROFILE(SMBsearch);
1413 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1416 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1417 conn->dirpath,lp_dontdescend(SNUM(conn))));
1418 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1419 check_descend = True;
1422 for (i=numentries;(i<maxentries) && !finished;i++) {
1423 finished = !get_dir_entry(ctx,
1434 char buf[DIR_STRUCT_SIZE];
1435 memcpy(buf,status,21);
1436 if (!make_dir_struct(ctx,
1443 !allow_long_path_components)) {
1444 reply_nterror(req, NT_STATUS_NO_MEMORY);
1445 END_PROFILE(SMBsearch);
1448 if (!dptr_fill(buf+12,dptr_num)) {
1451 if (message_push_blob(&req->outbuf,
1452 data_blob_const(buf, sizeof(buf)))
1454 reply_nterror(req, NT_STATUS_NO_MEMORY);
1455 END_PROFILE(SMBsearch);
1465 /* If we were called as SMBffirst with smb_search_id == NULL
1466 and no entries were found then return error and close dirptr
1469 if (numentries == 0) {
1470 dptr_close(&dptr_num);
1471 } else if(expect_close && status_len == 0) {
1472 /* Close the dptr - we know it's gone */
1473 dptr_close(&dptr_num);
1476 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1477 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1478 dptr_close(&dptr_num);
1481 if ((numentries == 0) && !mask_contains_wcard) {
1482 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1483 END_PROFILE(SMBsearch);
1487 SSVAL(req->outbuf,smb_vwv0,numentries);
1488 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1489 SCVAL(smb_buf(req->outbuf),0,5);
1490 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1492 /* The replies here are never long name. */
1493 SSVAL(req->outbuf, smb_flg2,
1494 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1495 if (!allow_long_path_components) {
1496 SSVAL(req->outbuf, smb_flg2,
1497 SVAL(req->outbuf, smb_flg2)
1498 & (~FLAGS2_LONG_PATH_COMPONENTS));
1501 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1502 SSVAL(req->outbuf, smb_flg2,
1503 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1506 directory = dptr_path(dptr_num);
1509 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1510 smb_fn_name(req->cmd),
1512 directory ? directory : "./",
1517 END_PROFILE(SMBsearch);
1521 /****************************************************************************
1522 Reply to a fclose (stop directory search).
1523 ****************************************************************************/
1525 void reply_fclose(struct smb_request *req)
1533 bool path_contains_wcard = False;
1534 TALLOC_CTX *ctx = talloc_tos();
1536 START_PROFILE(SMBfclose);
1538 if (lp_posix_pathnames()) {
1539 reply_unknown_new(req, req->cmd);
1540 END_PROFILE(SMBfclose);
1544 p = (const char *)req->buf + 1;
1545 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1546 &err, &path_contains_wcard);
1547 if (!NT_STATUS_IS_OK(err)) {
1548 reply_nterror(req, err);
1549 END_PROFILE(SMBfclose);
1553 status_len = SVAL(p,0);
1556 if (status_len == 0) {
1557 reply_doserror(req, ERRSRV, ERRsrverror);
1558 END_PROFILE(SMBfclose);
1562 memcpy(status,p,21);
1564 if(dptr_fetch(status+12,&dptr_num)) {
1565 /* Close the dptr - we know it's gone */
1566 dptr_close(&dptr_num);
1569 reply_outbuf(req, 1, 0);
1570 SSVAL(req->outbuf,smb_vwv0,0);
1572 DEBUG(3,("search close\n"));
1574 END_PROFILE(SMBfclose);
1578 /****************************************************************************
1580 ****************************************************************************/
1582 void reply_open(struct smb_request *req)
1584 connection_struct *conn = req->conn;
1590 SMB_STRUCT_STAT sbuf;
1597 uint32 create_disposition;
1598 uint32 create_options = 0;
1600 TALLOC_CTX *ctx = talloc_tos();
1602 START_PROFILE(SMBopen);
1605 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1606 END_PROFILE(SMBopen);
1610 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1611 deny_mode = SVAL(req->vwv+0, 0);
1612 dos_attr = SVAL(req->vwv+1, 0);
1614 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1615 STR_TERMINATE, &status);
1616 if (!NT_STATUS_IS_OK(status)) {
1617 reply_nterror(req, status);
1618 END_PROFILE(SMBopen);
1622 if (!map_open_params_to_ntcreate(
1623 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1624 &share_mode, &create_disposition, &create_options)) {
1625 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1626 END_PROFILE(SMBopen);
1630 status = SMB_VFS_CREATE_FILE(
1633 0, /* root_dir_fid */
1635 CFF_DOS_PATH, /* create_file_flags */
1636 access_mask, /* access_mask */
1637 share_mode, /* share_access */
1638 create_disposition, /* create_disposition*/
1639 create_options, /* create_options */
1640 dos_attr, /* file_attributes */
1641 oplock_request, /* oplock_request */
1642 0, /* allocation_size */
1649 if (!NT_STATUS_IS_OK(status)) {
1650 if (open_was_deferred(req->mid)) {
1651 /* We have re-scheduled this call. */
1652 END_PROFILE(SMBopen);
1655 reply_openerror(req, status);
1656 END_PROFILE(SMBopen);
1660 size = sbuf.st_size;
1661 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1662 mtime = sbuf.st_mtime;
1665 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1666 close_file(req, fsp, ERROR_CLOSE);
1667 reply_doserror(req, ERRDOS,ERRnoaccess);
1668 END_PROFILE(SMBopen);
1672 reply_outbuf(req, 7, 0);
1673 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1674 SSVAL(req->outbuf,smb_vwv1,fattr);
1675 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1676 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1678 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1680 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1681 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1683 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1684 SCVAL(req->outbuf,smb_flg,
1685 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1688 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1689 SCVAL(req->outbuf,smb_flg,
1690 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1692 END_PROFILE(SMBopen);
1696 /****************************************************************************
1697 Reply to an open and X.
1698 ****************************************************************************/
1700 void reply_open_and_X(struct smb_request *req)
1702 connection_struct *conn = req->conn;
1707 /* Breakout the oplock request bits so we can set the
1708 reply bits separately. */
1709 int ex_oplock_request;
1710 int core_oplock_request;
1713 int smb_sattr = SVAL(req->vwv+4, 0);
1714 uint32 smb_time = make_unix_date3(req->vwv+6);
1719 SMB_STRUCT_STAT sbuf;
1723 uint64_t allocation_size;
1724 ssize_t retval = -1;
1727 uint32 create_disposition;
1728 uint32 create_options = 0;
1729 TALLOC_CTX *ctx = talloc_tos();
1731 START_PROFILE(SMBopenX);
1733 if (req->wct < 15) {
1734 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1735 END_PROFILE(SMBopenX);
1739 open_flags = SVAL(req->vwv+2, 0);
1740 deny_mode = SVAL(req->vwv+3, 0);
1741 smb_attr = SVAL(req->vwv+5, 0);
1742 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1743 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1744 oplock_request = ex_oplock_request | core_oplock_request;
1745 smb_ofun = SVAL(req->vwv+8, 0);
1746 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1748 /* If it's an IPC, pass off the pipe handler. */
1750 if (lp_nt_pipe_support()) {
1751 reply_open_pipe_and_X(conn, req);
1753 reply_doserror(req, ERRSRV, ERRaccess);
1755 END_PROFILE(SMBopenX);
1759 /* XXXX we need to handle passed times, sattr and flags */
1760 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1761 STR_TERMINATE, &status);
1762 if (!NT_STATUS_IS_OK(status)) {
1763 reply_nterror(req, status);
1764 END_PROFILE(SMBopenX);
1768 if (!map_open_params_to_ntcreate(
1769 fname, deny_mode, smb_ofun, &access_mask,
1770 &share_mode, &create_disposition, &create_options)) {
1771 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1772 END_PROFILE(SMBopenX);
1776 status = SMB_VFS_CREATE_FILE(
1779 0, /* root_dir_fid */
1781 CFF_DOS_PATH, /* create_file_flags */
1782 access_mask, /* access_mask */
1783 share_mode, /* share_access */
1784 create_disposition, /* create_disposition*/
1785 create_options, /* create_options */
1786 smb_attr, /* file_attributes */
1787 oplock_request, /* oplock_request */
1788 0, /* allocation_size */
1792 &smb_action, /* pinfo */
1795 if (!NT_STATUS_IS_OK(status)) {
1796 END_PROFILE(SMBopenX);
1797 if (open_was_deferred(req->mid)) {
1798 /* We have re-scheduled this call. */
1801 reply_openerror(req, status);
1805 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1806 if the file is truncated or created. */
1807 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1808 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1809 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1810 close_file(req, fsp, ERROR_CLOSE);
1811 reply_nterror(req, NT_STATUS_DISK_FULL);
1812 END_PROFILE(SMBopenX);
1815 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1817 close_file(req, fsp, ERROR_CLOSE);
1818 reply_nterror(req, NT_STATUS_DISK_FULL);
1819 END_PROFILE(SMBopenX);
1822 sbuf.st_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
1825 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1826 mtime = sbuf.st_mtime;
1828 close_file(req, fsp, ERROR_CLOSE);
1829 reply_doserror(req, ERRDOS, ERRnoaccess);
1830 END_PROFILE(SMBopenX);
1834 /* If the caller set the extended oplock request bit
1835 and we granted one (by whatever means) - set the
1836 correct bit for extended oplock reply.
1839 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1840 smb_action |= EXTENDED_OPLOCK_GRANTED;
1843 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1844 smb_action |= EXTENDED_OPLOCK_GRANTED;
1847 /* If the caller set the core oplock request bit
1848 and we granted one (by whatever means) - set the
1849 correct bit for core oplock reply.
1852 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1853 reply_outbuf(req, 19, 0);
1855 reply_outbuf(req, 15, 0);
1858 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1859 SCVAL(req->outbuf, smb_flg,
1860 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1863 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1864 SCVAL(req->outbuf, smb_flg,
1865 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1868 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1869 SSVAL(req->outbuf,smb_vwv3,fattr);
1870 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1871 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1873 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1875 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1876 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1877 SSVAL(req->outbuf,smb_vwv11,smb_action);
1879 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1880 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1883 END_PROFILE(SMBopenX);
1888 /****************************************************************************
1889 Reply to a SMBulogoffX.
1890 ****************************************************************************/
1892 void reply_ulogoffX(struct smb_request *req)
1896 START_PROFILE(SMBulogoffX);
1898 vuser = get_valid_user_struct(req->vuid);
1901 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1905 /* in user level security we are supposed to close any files
1906 open by this user */
1907 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1908 file_close_user(req->vuid);
1911 invalidate_vuid(req->vuid);
1913 reply_outbuf(req, 2, 0);
1915 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1917 END_PROFILE(SMBulogoffX);
1921 /****************************************************************************
1922 Reply to a mknew or a create.
1923 ****************************************************************************/
1925 void reply_mknew(struct smb_request *req)
1927 connection_struct *conn = req->conn;
1930 struct smb_file_time ft;
1932 int oplock_request = 0;
1933 SMB_STRUCT_STAT sbuf;
1935 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1936 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1937 uint32 create_disposition;
1938 uint32 create_options = 0;
1939 TALLOC_CTX *ctx = talloc_tos();
1941 START_PROFILE(SMBcreate);
1945 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1946 END_PROFILE(SMBcreate);
1950 fattr = SVAL(req->vwv+0, 0);
1951 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1954 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
1956 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
1957 STR_TERMINATE, &status);
1958 if (!NT_STATUS_IS_OK(status)) {
1959 reply_nterror(req, status);
1960 END_PROFILE(SMBcreate);
1964 if (fattr & aVOLID) {
1965 DEBUG(0,("Attempt to create file (%s) with volid set - "
1966 "please report this\n", fname));
1969 if(req->cmd == SMBmknew) {
1970 /* We should fail if file exists. */
1971 create_disposition = FILE_CREATE;
1973 /* Create if file doesn't exist, truncate if it does. */
1974 create_disposition = FILE_OVERWRITE_IF;
1977 status = SMB_VFS_CREATE_FILE(
1980 0, /* root_dir_fid */
1982 CFF_DOS_PATH, /* create_file_flags */
1983 access_mask, /* access_mask */
1984 share_mode, /* share_access */
1985 create_disposition, /* create_disposition*/
1986 create_options, /* create_options */
1987 fattr, /* file_attributes */
1988 oplock_request, /* oplock_request */
1989 0, /* allocation_size */
1996 if (!NT_STATUS_IS_OK(status)) {
1997 END_PROFILE(SMBcreate);
1998 if (open_was_deferred(req->mid)) {
1999 /* We have re-scheduled this call. */
2002 reply_openerror(req, status);
2006 ft.atime = get_atimespec(&sbuf); /* atime. */
2007 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true);
2008 if (!NT_STATUS_IS_OK(status)) {
2009 END_PROFILE(SMBcreate);
2010 reply_openerror(req, status);
2014 reply_outbuf(req, 1, 0);
2015 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2017 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2018 SCVAL(req->outbuf,smb_flg,
2019 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2022 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2023 SCVAL(req->outbuf,smb_flg,
2024 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2027 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2028 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2029 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2031 END_PROFILE(SMBcreate);
2035 /****************************************************************************
2036 Reply to a create temporary file.
2037 ****************************************************************************/
2039 void reply_ctemp(struct smb_request *req)
2041 connection_struct *conn = req->conn;
2047 SMB_STRUCT_STAT sbuf;
2050 TALLOC_CTX *ctx = talloc_tos();
2052 START_PROFILE(SMBctemp);
2055 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2056 END_PROFILE(SMBctemp);
2060 fattr = SVAL(req->vwv+0, 0);
2061 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2063 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2064 STR_TERMINATE, &status);
2065 if (!NT_STATUS_IS_OK(status)) {
2066 reply_nterror(req, status);
2067 END_PROFILE(SMBctemp);
2071 fname = talloc_asprintf(ctx,
2075 fname = talloc_strdup(ctx, "TMXXXXXX");
2079 reply_nterror(req, NT_STATUS_NO_MEMORY);
2080 END_PROFILE(SMBctemp);
2084 status = resolve_dfspath(ctx, conn,
2085 req->flags2 & FLAGS2_DFS_PATHNAMES,
2088 if (!NT_STATUS_IS_OK(status)) {
2089 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2090 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2091 ERRSRV, ERRbadpath);
2092 END_PROFILE(SMBctemp);
2095 reply_nterror(req, status);
2096 END_PROFILE(SMBctemp);
2100 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
2101 if (!NT_STATUS_IS_OK(status)) {
2102 reply_nterror(req, status);
2103 END_PROFILE(SMBctemp);
2107 status = check_name(conn, fname);
2108 if (!NT_STATUS_IS_OK(status)) {
2109 reply_nterror(req, status);
2110 END_PROFILE(SMBctemp);
2114 tmpfd = smb_mkstemp(fname);
2116 reply_unixerror(req, ERRDOS, ERRnoaccess);
2117 END_PROFILE(SMBctemp);
2121 SMB_VFS_STAT(conn,fname,&sbuf);
2123 /* We should fail if file does not exist. */
2124 status = SMB_VFS_CREATE_FILE(
2127 0, /* root_dir_fid */
2129 0, /* create_file_flags */
2130 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2131 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2132 FILE_OPEN, /* create_disposition*/
2133 0, /* create_options */
2134 fattr, /* file_attributes */
2135 oplock_request, /* oplock_request */
2136 0, /* allocation_size */
2143 /* close fd from smb_mkstemp() */
2146 if (!NT_STATUS_IS_OK(status)) {
2147 if (open_was_deferred(req->mid)) {
2148 /* We have re-scheduled this call. */
2149 END_PROFILE(SMBctemp);
2152 reply_openerror(req, status);
2153 END_PROFILE(SMBctemp);
2157 reply_outbuf(req, 1, 0);
2158 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2160 /* the returned filename is relative to the directory */
2161 s = strrchr_m(fsp->fsp_name, '/');
2169 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2170 thing in the byte section. JRA */
2171 SSVALS(p, 0, -1); /* what is this? not in spec */
2173 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2175 reply_nterror(req, NT_STATUS_NO_MEMORY);
2176 END_PROFILE(SMBctemp);
2180 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2181 SCVAL(req->outbuf, smb_flg,
2182 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2185 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2186 SCVAL(req->outbuf, smb_flg,
2187 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2190 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2191 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2192 fsp->fh->fd, (unsigned int)sbuf.st_mode ) );
2194 END_PROFILE(SMBctemp);
2198 /*******************************************************************
2199 Check if a user is allowed to rename a file.
2200 ********************************************************************/
2202 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2203 uint16 dirtype, SMB_STRUCT_STAT *pst)
2207 if (!CAN_WRITE(conn)) {
2208 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2211 fmode = dos_mode(conn, fsp->fsp_name, pst);
2212 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2213 return NT_STATUS_NO_SUCH_FILE;
2216 if (S_ISDIR(pst->st_mode)) {
2217 return NT_STATUS_OK;
2220 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2221 return NT_STATUS_OK;
2224 return NT_STATUS_ACCESS_DENIED;
2227 /*******************************************************************
2228 * unlink a file with all relevant access checks
2229 *******************************************************************/
2231 static NTSTATUS do_unlink(connection_struct *conn,
2232 struct smb_request *req,
2236 SMB_STRUCT_STAT sbuf;
2239 uint32 dirtype_orig = dirtype;
2242 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2244 if (!CAN_WRITE(conn)) {
2245 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2248 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2249 return map_nt_error_from_unix(errno);
2252 fattr = dos_mode(conn,fname,&sbuf);
2254 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2255 dirtype = aDIR|aARCH|aRONLY;
2258 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2260 return NT_STATUS_NO_SUCH_FILE;
2263 if (!dir_check_ftype(conn, fattr, dirtype)) {
2265 return NT_STATUS_FILE_IS_A_DIRECTORY;
2267 return NT_STATUS_NO_SUCH_FILE;
2270 if (dirtype_orig & 0x8000) {
2271 /* These will never be set for POSIX. */
2272 return NT_STATUS_NO_SUCH_FILE;
2276 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2277 return NT_STATUS_FILE_IS_A_DIRECTORY;
2280 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2281 return NT_STATUS_NO_SUCH_FILE;
2284 if (dirtype & 0xFF00) {
2285 /* These will never be set for POSIX. */
2286 return NT_STATUS_NO_SUCH_FILE;
2291 return NT_STATUS_NO_SUCH_FILE;
2294 /* Can't delete a directory. */
2296 return NT_STATUS_FILE_IS_A_DIRECTORY;
2301 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2302 return NT_STATUS_OBJECT_NAME_INVALID;
2303 #endif /* JRATEST */
2305 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2307 On a Windows share, a file with read-only dosmode can be opened with
2308 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2309 fails with NT_STATUS_CANNOT_DELETE error.
2311 This semantic causes a problem that a user can not
2312 rename a file with read-only dosmode on a Samba share
2313 from a Windows command prompt (i.e. cmd.exe, but can rename
2314 from Windows Explorer).
2317 if (!lp_delete_readonly(SNUM(conn))) {
2318 if (fattr & aRONLY) {
2319 return NT_STATUS_CANNOT_DELETE;
2323 /* On open checks the open itself will check the share mode, so
2324 don't do it here as we'll get it wrong. */
2326 status = SMB_VFS_CREATE_FILE
2329 0, /* root_dir_fid */
2331 0, /* create_file_flags */
2332 DELETE_ACCESS, /* access_mask */
2333 FILE_SHARE_NONE, /* share_access */
2334 FILE_OPEN, /* create_disposition*/
2335 FILE_NON_DIRECTORY_FILE, /* create_options */
2336 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2337 0, /* oplock_request */
2338 0, /* allocation_size */
2345 if (!NT_STATUS_IS_OK(status)) {
2346 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2347 nt_errstr(status)));
2351 /* The set is across all open files on this dev/inode pair. */
2352 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2353 close_file(req, fsp, NORMAL_CLOSE);
2354 return NT_STATUS_ACCESS_DENIED;
2357 return close_file(req, fsp, NORMAL_CLOSE);
2360 /****************************************************************************
2361 The guts of the unlink command, split out so it may be called by the NT SMB
2363 ****************************************************************************/
2365 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2366 uint32 dirtype, const char *name_in, bool has_wild)
2368 const char *directory = NULL;
2373 NTSTATUS status = NT_STATUS_OK;
2374 SMB_STRUCT_STAT sbuf, st;
2375 TALLOC_CTX *ctx = talloc_tos();
2377 status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
2378 if (!NT_STATUS_IS_OK(status)) {
2382 p = strrchr_m(name,'/');
2384 directory = talloc_strdup(ctx, ".");
2386 return NT_STATUS_NO_MEMORY;
2396 * We should only check the mangled cache
2397 * here if unix_convert failed. This means
2398 * that the path in 'mask' doesn't exist
2399 * on the file system and so we need to look
2400 * for a possible mangle. This patch from
2401 * Tine Smukavec <valentin.smukavec@hermes.si>.
2404 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
2405 char *new_mask = NULL;
2406 mangle_lookup_name_from_8_3(ctx,
2416 directory = talloc_asprintf(ctx,
2421 return NT_STATUS_NO_MEMORY;
2424 dirtype = FILE_ATTRIBUTE_NORMAL;
2427 status = check_name(conn, directory);
2428 if (!NT_STATUS_IS_OK(status)) {
2432 status = do_unlink(conn, req, directory, dirtype);
2433 if (!NT_STATUS_IS_OK(status)) {
2439 struct smb_Dir *dir_hnd = NULL;
2443 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2444 return NT_STATUS_OBJECT_NAME_INVALID;
2447 if (strequal(mask,"????????.???")) {
2452 status = check_name(conn, directory);
2453 if (!NT_STATUS_IS_OK(status)) {
2457 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2459 if (dir_hnd == NULL) {
2460 return map_nt_error_from_unix(errno);
2463 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2464 the pattern matches against the long name, otherwise the short name
2465 We don't implement this yet XXXX
2468 status = NT_STATUS_NO_SUCH_FILE;
2470 while ((dname = ReadDirName(dir_hnd, &offset, &st))) {
2473 if (!is_visible_file(conn, directory, dname, &st,
2479 /* Quick check for "." and ".." */
2480 if (ISDOT(dname) || ISDOTDOT(dname)) {
2484 if(!mask_match(dname, mask, conn->case_sensitive)) {
2488 fname = talloc_asprintf(ctx, "%s/%s",
2492 return NT_STATUS_NO_MEMORY;
2495 status = check_name(conn, fname);
2496 if (!NT_STATUS_IS_OK(status)) {
2497 TALLOC_FREE(dir_hnd);
2501 status = do_unlink(conn, req, fname, dirtype);
2502 if (!NT_STATUS_IS_OK(status)) {
2508 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2513 TALLOC_FREE(dir_hnd);
2516 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2517 status = map_nt_error_from_unix(errno);
2523 /****************************************************************************
2525 ****************************************************************************/
2527 void reply_unlink(struct smb_request *req)
2529 connection_struct *conn = req->conn;
2533 bool path_contains_wcard = False;
2534 TALLOC_CTX *ctx = talloc_tos();
2536 START_PROFILE(SMBunlink);
2539 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2540 END_PROFILE(SMBunlink);
2544 dirtype = SVAL(req->vwv+0, 0);
2546 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2547 STR_TERMINATE, &status,
2548 &path_contains_wcard);
2549 if (!NT_STATUS_IS_OK(status)) {
2550 reply_nterror(req, status);
2551 END_PROFILE(SMBunlink);
2555 status = resolve_dfspath_wcard(ctx, conn,
2556 req->flags2 & FLAGS2_DFS_PATHNAMES,
2559 &path_contains_wcard);
2560 if (!NT_STATUS_IS_OK(status)) {
2561 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2562 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2563 ERRSRV, ERRbadpath);
2564 END_PROFILE(SMBunlink);
2567 reply_nterror(req, status);
2568 END_PROFILE(SMBunlink);
2572 DEBUG(3,("reply_unlink : %s\n",name));
2574 status = unlink_internals(conn, req, dirtype, name,
2575 path_contains_wcard);
2576 if (!NT_STATUS_IS_OK(status)) {
2577 if (open_was_deferred(req->mid)) {
2578 /* We have re-scheduled this call. */
2579 END_PROFILE(SMBunlink);
2582 reply_nterror(req, status);
2583 END_PROFILE(SMBunlink);
2587 reply_outbuf(req, 0, 0);
2588 END_PROFILE(SMBunlink);
2593 /****************************************************************************
2595 ****************************************************************************/
2597 static void fail_readraw(void)
2599 const char *errstr = talloc_asprintf(talloc_tos(),
2600 "FAIL ! reply_readbraw: socket write fail (%s)",
2605 exit_server_cleanly(errstr);
2608 /****************************************************************************
2609 Fake (read/write) sendfile. Returns -1 on read or write fail.
2610 ****************************************************************************/
2612 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2616 size_t tosend = nread;
2623 bufsize = MIN(nread, 65536);
2625 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2629 while (tosend > 0) {
2633 if (tosend > bufsize) {
2638 ret = read_file(fsp,buf,startpos,cur_read);
2644 /* If we had a short read, fill with zeros. */
2645 if (ret < cur_read) {
2646 memset(buf, '\0', cur_read - ret);
2649 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2654 startpos += cur_read;
2658 return (ssize_t)nread;
2661 /****************************************************************************
2662 Deal with the case of sendfile reading less bytes from the file than
2663 requested. Fill with zeros (all we can do).
2664 ****************************************************************************/
2666 static void sendfile_short_send(files_struct *fsp,
2671 if (nread < headersize) {
2672 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2673 "header for file %s (%s). Terminating\n",
2674 fsp->fsp_name, strerror(errno) ));
2675 exit_server_cleanly("sendfile_short_send failed");
2678 nread -= headersize;
2680 if (nread < smb_maxcnt) {
2681 char *buf = SMB_CALLOC_ARRAY(char, 1024);
2683 exit_server_cleanly("sendfile_short_send: "
2687 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2688 "with zeros !\n", fsp->fsp_name));
2690 while (nread < smb_maxcnt) {
2692 * We asked for the real file size and told sendfile
2693 * to not go beyond the end of the file. But it can
2694 * happen that in between our fstat call and the
2695 * sendfile call the file was truncated. This is very
2696 * bad because we have already announced the larger
2697 * number of bytes to the client.
2699 * The best we can do now is to send 0-bytes, just as
2700 * a read from a hole in a sparse file would do.
2702 * This should happen rarely enough that I don't care
2703 * about efficiency here :-)
2707 to_write = MIN(sizeof(buf), smb_maxcnt - nread);
2708 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2709 exit_server_cleanly("sendfile_short_send: "
2710 "write_data failed");
2718 /****************************************************************************
2719 Return a readbraw error (4 bytes of zero).
2720 ****************************************************************************/
2722 static void reply_readbraw_error(void)
2726 if (write_data(smbd_server_fd(),header,4) != 4) {
2731 /****************************************************************************
2732 Use sendfile in readbraw.
2733 ****************************************************************************/
2735 static void send_file_readbraw(connection_struct *conn,
2736 struct smb_request *req,
2742 char *outbuf = NULL;
2745 #if defined(WITH_SENDFILE)
2747 * We can only use sendfile on a non-chained packet
2748 * but we can use on a non-oplocked file. tridge proved this
2749 * on a train in Germany :-). JRA.
2750 * reply_readbraw has already checked the length.
2753 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2754 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2755 ssize_t sendfile_read = -1;
2757 DATA_BLOB header_blob;
2759 _smb_setlen(header,nread);
2760 header_blob = data_blob_const(header, 4);
2762 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2763 &header_blob, startpos, nread)) == -1) {
2764 /* Returning ENOSYS means no data at all was sent.
2765 * Do this as a normal read. */
2766 if (errno == ENOSYS) {
2767 goto normal_readbraw;
2771 * Special hack for broken Linux with no working sendfile. If we
2772 * return EINTR we sent the header but not the rest of the data.
2773 * Fake this up by doing read/write calls.
2775 if (errno == EINTR) {
2776 /* Ensure we don't do this again. */
2777 set_use_sendfile(SNUM(conn), False);
2778 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2780 if (fake_sendfile(fsp, startpos, nread) == -1) {
2781 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2782 fsp->fsp_name, strerror(errno) ));
2783 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2788 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2789 fsp->fsp_name, strerror(errno) ));
2790 exit_server_cleanly("send_file_readbraw sendfile failed");
2791 } else if (sendfile_read == 0) {
2793 * Some sendfile implementations return 0 to indicate
2794 * that there was a short read, but nothing was
2795 * actually written to the socket. In this case,
2796 * fallback to the normal read path so the header gets
2797 * the correct byte count.
2799 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2800 "bytes falling back to the normal read: "
2801 "%s\n", fsp->fsp_name));
2802 goto normal_readbraw;
2805 /* Deal with possible short send. */
2806 if (sendfile_read != 4+nread) {
2807 sendfile_short_send(fsp, sendfile_read, 4, nread);
2815 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2817 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2818 (unsigned)(nread+4)));
2819 reply_readbraw_error();
2824 ret = read_file(fsp,outbuf+4,startpos,nread);
2825 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2834 _smb_setlen(outbuf,ret);
2835 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2838 TALLOC_FREE(outbuf);
2841 /****************************************************************************
2842 Reply to a readbraw (core+ protocol).
2843 ****************************************************************************/
2845 void reply_readbraw(struct smb_request *req)
2847 connection_struct *conn = req->conn;
2848 ssize_t maxcount,mincount;
2855 START_PROFILE(SMBreadbraw);
2857 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
2858 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2859 "raw reads/writes are disallowed.");
2863 reply_readbraw_error();
2864 END_PROFILE(SMBreadbraw);
2869 * Special check if an oplock break has been issued
2870 * and the readraw request croses on the wire, we must
2871 * return a zero length response here.
2874 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2877 * We have to do a check_fsp by hand here, as
2878 * we must always return 4 zero bytes on error,
2882 if (!fsp || !conn || conn != fsp->conn ||
2883 req->vuid != fsp->vuid ||
2884 fsp->is_directory || fsp->fh->fd == -1) {
2886 * fsp could be NULL here so use the value from the packet. JRA.
2888 DEBUG(3,("reply_readbraw: fnum %d not valid "
2890 (int)SVAL(req->vwv+0, 0)));
2891 reply_readbraw_error();
2892 END_PROFILE(SMBreadbraw);
2896 /* Do a "by hand" version of CHECK_READ. */
2897 if (!(fsp->can_read ||
2898 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2899 (fsp->access_mask & FILE_EXECUTE)))) {
2900 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2901 (int)SVAL(req->vwv+0, 0)));
2902 reply_readbraw_error();
2903 END_PROFILE(SMBreadbraw);
2907 flush_write_cache(fsp, READRAW_FLUSH);
2909 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
2910 if(req->wct == 10) {
2912 * This is a large offset (64 bit) read.
2914 #ifdef LARGE_SMB_OFF_T
2916 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
2918 #else /* !LARGE_SMB_OFF_T */
2921 * Ensure we haven't been sent a >32 bit offset.
2924 if(IVAL(req->vwv+8, 0) != 0) {
2925 DEBUG(0,("reply_readbraw: large offset "
2926 "(%x << 32) used and we don't support "
2927 "64 bit offsets.\n",
2928 (unsigned int)IVAL(req->vwv+8, 0) ));
2929 reply_readbraw_error();
2930 END_PROFILE(SMBreadbraw);
2934 #endif /* LARGE_SMB_OFF_T */
2937 DEBUG(0,("reply_readbraw: negative 64 bit "
2938 "readraw offset (%.0f) !\n",
2939 (double)startpos ));
2940 reply_readbraw_error();
2941 END_PROFILE(SMBreadbraw);
2946 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
2947 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
2949 /* ensure we don't overrun the packet size */
2950 maxcount = MIN(65535,maxcount);
2952 if (is_locked(fsp,(uint32)req->smbpid,
2956 reply_readbraw_error();
2957 END_PROFILE(SMBreadbraw);
2961 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
2965 if (startpos >= size) {
2968 nread = MIN(maxcount,(size - startpos));
2971 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2972 if (nread < mincount)
2976 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2977 "min=%lu nread=%lu\n",
2978 fsp->fnum, (double)startpos,
2979 (unsigned long)maxcount,
2980 (unsigned long)mincount,
2981 (unsigned long)nread ) );
2983 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
2985 DEBUG(5,("reply_readbraw finished\n"));
2986 END_PROFILE(SMBreadbraw);
2990 #define DBGC_CLASS DBGC_LOCKING
2992 /****************************************************************************
2993 Reply to a lockread (core+ protocol).
2994 ****************************************************************************/
2996 void reply_lockread(struct smb_request *req)
2998 connection_struct *conn = req->conn;
3005 struct byte_range_lock *br_lck = NULL;
3008 START_PROFILE(SMBlockread);
3011 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3012 END_PROFILE(SMBlockread);
3016 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3018 if (!check_fsp(conn, req, fsp)) {
3019 END_PROFILE(SMBlockread);
3023 if (!CHECK_READ(fsp,req)) {
3024 reply_doserror(req, ERRDOS, ERRbadaccess);
3025 END_PROFILE(SMBlockread);
3029 numtoread = SVAL(req->vwv+1, 0);
3030 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3032 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3034 reply_outbuf(req, 5, numtoread + 3);
3036 data = smb_buf(req->outbuf) + 3;
3039 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3040 * protocol request that predates the read/write lock concept.
3041 * Thus instead of asking for a read lock here we need to ask
3042 * for a write lock. JRA.
3043 * Note that the requested lock size is unaffected by max_recv.
3046 br_lck = do_lock(smbd_messaging_context(),
3049 (uint64_t)numtoread,
3053 False, /* Non-blocking lock. */
3057 TALLOC_FREE(br_lck);
3059 if (NT_STATUS_V(status)) {
3060 reply_nterror(req, status);
3061 END_PROFILE(SMBlockread);
3066 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3069 if (numtoread > max_recv) {
3070 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3071 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3072 (unsigned int)numtoread, (unsigned int)max_recv ));
3073 numtoread = MIN(numtoread,max_recv);
3075 nread = read_file(fsp,data,startpos,numtoread);
3078 reply_unixerror(req, ERRDOS, ERRnoaccess);
3079 END_PROFILE(SMBlockread);
3083 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3085 SSVAL(req->outbuf,smb_vwv0,nread);
3086 SSVAL(req->outbuf,smb_vwv5,nread+3);
3087 p = smb_buf(req->outbuf);
3088 SCVAL(p,0,0); /* pad byte. */
3091 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3092 fsp->fnum, (int)numtoread, (int)nread));
3094 END_PROFILE(SMBlockread);
3099 #define DBGC_CLASS DBGC_ALL
3101 /****************************************************************************
3103 ****************************************************************************/
3105 void reply_read(struct smb_request *req)
3107 connection_struct *conn = req->conn;
3115 START_PROFILE(SMBread);
3118 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3119 END_PROFILE(SMBread);
3123 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3125 if (!check_fsp(conn, req, fsp)) {
3126 END_PROFILE(SMBread);
3130 if (!CHECK_READ(fsp,req)) {
3131 reply_doserror(req, ERRDOS, ERRbadaccess);
3132 END_PROFILE(SMBread);
3136 numtoread = SVAL(req->vwv+1, 0);
3137 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3139 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3142 * The requested read size cannot be greater than max_recv. JRA.
3144 if (numtoread > max_recv) {
3145 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3146 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3147 (unsigned int)numtoread, (unsigned int)max_recv ));
3148 numtoread = MIN(numtoread,max_recv);
3151 reply_outbuf(req, 5, numtoread+3);
3153 data = smb_buf(req->outbuf) + 3;
3155 if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtoread,
3156 (uint64_t)startpos, READ_LOCK)) {
3157 reply_doserror(req, ERRDOS,ERRlock);
3158 END_PROFILE(SMBread);
3163 nread = read_file(fsp,data,startpos,numtoread);
3166 reply_unixerror(req, ERRDOS,ERRnoaccess);
3167 END_PROFILE(SMBread);
3171 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3173 SSVAL(req->outbuf,smb_vwv0,nread);
3174 SSVAL(req->outbuf,smb_vwv5,nread+3);
3175 SCVAL(smb_buf(req->outbuf),0,1);
3176 SSVAL(smb_buf(req->outbuf),1,nread);
3178 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3179 fsp->fnum, (int)numtoread, (int)nread ) );
3181 END_PROFILE(SMBread);
3185 /****************************************************************************
3187 ****************************************************************************/
3189 static int setup_readX_header(struct smb_request *req, char *outbuf,
3195 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3196 data = smb_buf(outbuf);
3198 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3200 SCVAL(outbuf,smb_vwv0,0xFF);
3201 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3202 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3203 SSVAL(outbuf,smb_vwv6,
3205 + 1 /* the wct field */
3206 + 12 * sizeof(uint16_t) /* vwv */
3207 + 2); /* the buflen field */
3208 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3209 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3210 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3211 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3215 /****************************************************************************
3216 Reply to a read and X - possibly using sendfile.
3217 ****************************************************************************/
3219 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3220 files_struct *fsp, SMB_OFF_T startpos,
3223 SMB_STRUCT_STAT sbuf;
3226 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3227 reply_unixerror(req, ERRDOS, ERRnoaccess);
3231 if (startpos > sbuf.st_size) {
3233 } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
3234 smb_maxcnt = (sbuf.st_size - startpos);
3237 if (smb_maxcnt == 0) {
3241 #if defined(WITH_SENDFILE)
3243 * We can only use sendfile on a non-chained packet
3244 * but we can use on a non-oplocked file. tridge proved this
3245 * on a train in Germany :-). JRA.
3248 if (!req_is_in_chain(req) &&
3249 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3250 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
3251 uint8 headerbuf[smb_size + 12 * 2];
3255 * Set up the packet header before send. We
3256 * assume here the sendfile will work (get the
3257 * correct amount of data).
3260 header = data_blob_const(headerbuf, sizeof(headerbuf));
3262 construct_reply_common_req(req, (char *)headerbuf);
3263 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3265 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3266 /* Returning ENOSYS means no data at all was sent.
3267 Do this as a normal read. */
3268 if (errno == ENOSYS) {
3273 * Special hack for broken Linux with no working sendfile. If we
3274 * return EINTR we sent the header but not the rest of the data.
3275 * Fake this up by doing read/write calls.
3278 if (errno == EINTR) {
3279 /* Ensure we don't do this again. */
3280 set_use_sendfile(SNUM(conn), False);
3281 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3282 nread = fake_sendfile(fsp, startpos,
3285 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3286 fsp->fsp_name, strerror(errno) ));
3287 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3289 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3290 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3291 /* No outbuf here means successful sendfile. */
3292 TALLOC_FREE(req->outbuf);
3296 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3297 fsp->fsp_name, strerror(errno) ));
3298 exit_server_cleanly("send_file_readX sendfile failed");
3299 } else if (nread == 0) {
3301 * Some sendfile implementations return 0 to indicate
3302 * that there was a short read, but nothing was
3303 * actually written to the socket. In this case,
3304 * fallback to the normal read path so the header gets
3305 * the correct byte count.
3307 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3308 "falling back to the normal read: %s\n",
3313 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3314 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3316 /* Deal with possible short send. */
3317 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3318 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3321 /* No outbuf here means successful sendfile. */
3322 TALLOC_FREE(req->outbuf);
3323 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3324 SMB_PERFCOUNT_END(&req->pcd);
3331 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3332 uint8 headerbuf[smb_size + 2*12];
3334 construct_reply_common_req(req, (char *)headerbuf);
3335 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3337 /* Send out the header. */
3338 if (write_data(smbd_server_fd(), (char *)headerbuf,
3339 sizeof(headerbuf)) != sizeof(headerbuf)) {
3340 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3341 fsp->fsp_name, strerror(errno) ));
3342 exit_server_cleanly("send_file_readX sendfile failed");
3344 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3346 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3347 fsp->fsp_name, strerror(errno) ));
3348 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3350 TALLOC_FREE(req->outbuf);
3354 reply_outbuf(req, 12, smb_maxcnt);
3356 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3358 reply_unixerror(req, ERRDOS, ERRnoaccess);
3362 setup_readX_header(req, (char *)req->outbuf, nread);
3364 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3365 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3370 /****************************************************************************
3371 Reply to a read and X.
3372 ****************************************************************************/
3374 void reply_read_and_X(struct smb_request *req)
3376 connection_struct *conn = req->conn;
3380 bool big_readX = False;
3382 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3385 START_PROFILE(SMBreadX);
3387 if ((req->wct != 10) && (req->wct != 12)) {
3388 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3392 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3393 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3394 smb_maxcnt = SVAL(req->vwv+5, 0);
3396 /* If it's an IPC, pass off the pipe handler. */
3398 reply_pipe_read_and_X(req);
3399 END_PROFILE(SMBreadX);
3403 if (!check_fsp(conn, req, fsp)) {
3404 END_PROFILE(SMBreadX);
3408 if (!CHECK_READ(fsp,req)) {
3409 reply_doserror(req, ERRDOS,ERRbadaccess);
3410 END_PROFILE(SMBreadX);
3414 if (global_client_caps & CAP_LARGE_READX) {
3415 size_t upper_size = SVAL(req->vwv+7, 0);
3416 smb_maxcnt |= (upper_size<<16);
3417 if (upper_size > 1) {
3418 /* Can't do this on a chained packet. */
3419 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3420 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3421 END_PROFILE(SMBreadX);
3424 /* We currently don't do this on signed or sealed data. */
3425 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
3426 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3427 END_PROFILE(SMBreadX);
3430 /* Is there room in the reply for this data ? */
3431 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3433 NT_STATUS_INVALID_PARAMETER);
3434 END_PROFILE(SMBreadX);
3441 if (req->wct == 12) {
3442 #ifdef LARGE_SMB_OFF_T
3444 * This is a large offset (64 bit) read.
3446 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3448 #else /* !LARGE_SMB_OFF_T */
3451 * Ensure we haven't been sent a >32 bit offset.
3454 if(IVAL(req->vwv+10, 0) != 0) {
3455 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3456 "used and we don't support 64 bit offsets.\n",
3457 (unsigned int)IVAL(req->vwv+10, 0) ));
3458 END_PROFILE(SMBreadX);
3459 reply_doserror(req, ERRDOS, ERRbadaccess);
3463 #endif /* LARGE_SMB_OFF_T */
3467 if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)smb_maxcnt,
3468 (uint64_t)startpos, READ_LOCK)) {
3469 END_PROFILE(SMBreadX);
3470 reply_doserror(req, ERRDOS, ERRlock);
3475 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3476 END_PROFILE(SMBreadX);
3480 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3482 END_PROFILE(SMBreadX);
3486 /****************************************************************************
3487 Error replies to writebraw must have smb_wct == 1. Fix this up.
3488 ****************************************************************************/
3490 void error_to_writebrawerr(struct smb_request *req)
3492 uint8 *old_outbuf = req->outbuf;
3494 reply_outbuf(req, 1, 0);
3496 memcpy(req->outbuf, old_outbuf, smb_size);
3497 TALLOC_FREE(old_outbuf);
3500 /****************************************************************************
3501 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3502 ****************************************************************************/
3504 void reply_writebraw(struct smb_request *req)
3506 connection_struct *conn = req->conn;
3509 ssize_t total_written=0;
3510 size_t numtowrite=0;
3518 START_PROFILE(SMBwritebraw);
3521 * If we ever reply with an error, it must have the SMB command
3522 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3525 SCVAL(req->inbuf,smb_com,SMBwritec);
3527 if (srv_is_signing_active()) {
3528 END_PROFILE(SMBwritebraw);
3529 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3530 "raw reads/writes are disallowed.");
3533 if (req->wct < 12) {
3534 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3535 error_to_writebrawerr(req);
3536 END_PROFILE(SMBwritebraw);
3540 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3541 if (!check_fsp(conn, req, fsp)) {
3542 error_to_writebrawerr(req);
3543 END_PROFILE(SMBwritebraw);
3547 if (!CHECK_WRITE(fsp)) {
3548 reply_doserror(req, ERRDOS, ERRbadaccess);
3549 error_to_writebrawerr(req);
3550 END_PROFILE(SMBwritebraw);
3554 tcount = IVAL(req->vwv+1, 0);
3555 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3556 write_through = BITSETW(req->vwv+7,0);
3558 /* We have to deal with slightly different formats depending
3559 on whether we are using the core+ or lanman1.0 protocol */
3561 if(Protocol <= PROTOCOL_COREPLUS) {
3562 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3563 data = smb_buf(req->inbuf);
3565 numtowrite = SVAL(req->vwv+10, 0);
3566 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3569 /* Ensure we don't write bytes past the end of this packet. */
3570 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3571 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3572 error_to_writebrawerr(req);
3573 END_PROFILE(SMBwritebraw);
3577 if (is_locked(fsp,(uint32)req->smbpid,(uint64_t)tcount,
3578 (uint64_t)startpos, WRITE_LOCK)) {
3579 reply_doserror(req, ERRDOS, ERRlock);
3580 error_to_writebrawerr(req);
3581 END_PROFILE(SMBwritebraw);
3586 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3589 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3590 "wrote=%d sync=%d\n",
3591 fsp->fnum, (double)startpos, (int)numtowrite,
3592 (int)nwritten, (int)write_through));
3594 if (nwritten < (ssize_t)numtowrite) {
3595 reply_unixerror(req, ERRHRD, ERRdiskfull);
3596 error_to_writebrawerr(req);
3597 END_PROFILE(SMBwritebraw);
3601 total_written = nwritten;
3603 /* Allocate a buffer of 64k + length. */
3604 buf = TALLOC_ARRAY(NULL, char, 65540);
3606 reply_doserror(req, ERRDOS, ERRnomem);
3607 error_to_writebrawerr(req);
3608 END_PROFILE(SMBwritebraw);
3612 /* Return a SMBwritebraw message to the redirector to tell
3613 * it to send more bytes */
3615 memcpy(buf, req->inbuf, smb_size);
3616 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3617 SCVAL(buf,smb_com,SMBwritebraw);
3618 SSVALS(buf,smb_vwv0,0xFFFF);
3620 if (!srv_send_smb(smbd_server_fd(),
3622 IS_CONN_ENCRYPTED(conn),
3624 exit_server_cleanly("reply_writebraw: srv_send_smb "
3628 /* Now read the raw data into the buffer and write it */
3629 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3631 if (!NT_STATUS_IS_OK(status)) {
3632 exit_server_cleanly("secondary writebraw failed");
3635 /* Set up outbuf to return the correct size */
3636 reply_outbuf(req, 1, 0);
3638 if (numtowrite != 0) {
3640 if (numtowrite > 0xFFFF) {
3641 DEBUG(0,("reply_writebraw: Oversize secondary write "
3642 "raw requested (%u). Terminating\n",
3643 (unsigned int)numtowrite ));
3644 exit_server_cleanly("secondary writebraw failed");
3647 if (tcount > nwritten+numtowrite) {
3648 DEBUG(3,("reply_writebraw: Client overestimated the "
3650 (int)tcount,(int)nwritten,(int)numtowrite));
3653 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3655 if (!NT_STATUS_IS_OK(status)) {
3656 DEBUG(0,("reply_writebraw: Oversize secondary write "
3657 "raw read failed (%s). Terminating\n",
3658 nt_errstr(status)));
3659 exit_server_cleanly("secondary writebraw failed");
3662 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3663 if (nwritten == -1) {
3665 reply_unixerror(req, ERRHRD, ERRdiskfull);
3666 error_to_writebrawerr(req);
3667 END_PROFILE(SMBwritebraw);
3671 if (nwritten < (ssize_t)numtowrite) {
3672 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3673 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3677 total_written += nwritten;
3682 SSVAL(req->outbuf,smb_vwv0,total_written);
3684 status = sync_file(conn, fsp, write_through);
3685 if (!NT_STATUS_IS_OK(status)) {
3686 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3687 fsp->fsp_name, nt_errstr(status) ));
3688 reply_nterror(req, status);
3689 error_to_writebrawerr(req);
3690 END_PROFILE(SMBwritebraw);
3694 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3696 fsp->fnum, (double)startpos, (int)numtowrite,
3697 (int)total_written));
3699 /* We won't return a status if write through is not selected - this
3700 * follows what WfWg does */
3701 END_PROFILE(SMBwritebraw);
3703 if (!write_through && total_written==tcount) {
3705 #if RABBIT_PELLET_FIX
3707 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3708 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3711 if (!send_keepalive(smbd_server_fd())) {
3712 exit_server_cleanly("reply_writebraw: send of "
3713 "keepalive failed");
3716 TALLOC_FREE(req->outbuf);
3722 #define DBGC_CLASS DBGC_LOCKING
3724 /****************************************************************************
3725 Reply to a writeunlock (core+).
3726 ****************************************************************************/
3728 void reply_writeunlock(struct smb_request *req)
3730 connection_struct *conn = req->conn;
3731 ssize_t nwritten = -1;
3735 NTSTATUS status = NT_STATUS_OK;
3738 START_PROFILE(SMBwriteunlock);
3741 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3742 END_PROFILE(SMBwriteunlock);
3746 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3748 if (!check_fsp(conn, req, fsp)) {
3749 END_PROFILE(SMBwriteunlock);
3753 if (!CHECK_WRITE(fsp)) {
3754 reply_doserror(req, ERRDOS,ERRbadaccess);
3755 END_PROFILE(SMBwriteunlock);
3759 numtowrite = SVAL(req->vwv+1, 0);
3760 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3761 data = (const char *)req->buf + 3;
3764 && is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
3765 (uint64_t)startpos, WRITE_LOCK)) {
3766 reply_doserror(req, ERRDOS, ERRlock);
3767 END_PROFILE(SMBwriteunlock);
3771 /* The special X/Open SMB protocol handling of
3772 zero length writes is *NOT* done for
3774 if(numtowrite == 0) {
3777 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3780 status = sync_file(conn, fsp, False /* write through */);
3781 if (!NT_STATUS_IS_OK(status)) {
3782 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3783 fsp->fsp_name, nt_errstr(status) ));
3784 reply_nterror(req, status);
3785 END_PROFILE(SMBwriteunlock);
3789 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3790 reply_unixerror(req, ERRHRD, ERRdiskfull);
3791 END_PROFILE(SMBwriteunlock);
3796 status = do_unlock(smbd_messaging_context(),
3799 (uint64_t)numtowrite,
3803 if (NT_STATUS_V(status)) {
3804 reply_nterror(req, status);
3805 END_PROFILE(SMBwriteunlock);
3810 reply_outbuf(req, 1, 0);
3812 SSVAL(req->outbuf,smb_vwv0,nwritten);
3814 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3815 fsp->fnum, (int)numtowrite, (int)nwritten));
3817 END_PROFILE(SMBwriteunlock);
3822 #define DBGC_CLASS DBGC_ALL
3824 /****************************************************************************
3826 ****************************************************************************/
3828 void reply_write(struct smb_request *req)
3830 connection_struct *conn = req->conn;
3832 ssize_t nwritten = -1;
3838 START_PROFILE(SMBwrite);
3841 END_PROFILE(SMBwrite);
3842 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3846 /* If it's an IPC, pass off the pipe handler. */
3848 reply_pipe_write(req);
3849 END_PROFILE(SMBwrite);
3853 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3855 if (!check_fsp(conn, req, fsp)) {
3856 END_PROFILE(SMBwrite);
3860 if (!CHECK_WRITE(fsp)) {
3861 reply_doserror(req, ERRDOS, ERRbadaccess);
3862 END_PROFILE(SMBwrite);
3866 numtowrite = SVAL(req->vwv+1, 0);
3867 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3868 data = (const char *)req->buf + 3;
3870 if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
3871 (uint64_t)startpos, WRITE_LOCK)) {
3872 reply_doserror(req, ERRDOS, ERRlock);
3873 END_PROFILE(SMBwrite);
3878 * X/Open SMB protocol says that if smb_vwv1 is
3879 * zero then the file size should be extended or
3880 * truncated to the size given in smb_vwv[2-3].
3883 if(numtowrite == 0) {
3885 * This is actually an allocate call, and set EOF. JRA.
3887 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3889 reply_nterror(req, NT_STATUS_DISK_FULL);
3890 END_PROFILE(SMBwrite);
3893 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3895 reply_nterror(req, NT_STATUS_DISK_FULL);
3896 END_PROFILE(SMBwrite);
3899 trigger_write_time_update_immediate(fsp);
3901 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3904 status = sync_file(conn, fsp, False);
3905 if (!NT_STATUS_IS_OK(status)) {
3906 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3907 fsp->fsp_name, nt_errstr(status) ));
3908 reply_nterror(req, status);
3909 END_PROFILE(SMBwrite);
3913 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3914 reply_unixerror(req, ERRHRD, ERRdiskfull);
3915 END_PROFILE(SMBwrite);
3919 reply_outbuf(req, 1, 0);
3921 SSVAL(req->outbuf,smb_vwv0,nwritten);
3923 if (nwritten < (ssize_t)numtowrite) {
3924 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3925 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3928 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3930 END_PROFILE(SMBwrite);
3934 /****************************************************************************
3935 Ensure a buffer is a valid writeX for recvfile purposes.
3936 ****************************************************************************/
3938 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3939 (2*14) + /* word count (including bcc) */ \
3942 bool is_valid_writeX_buffer(const uint8_t *inbuf)
3945 connection_struct *conn = NULL;
3946 unsigned int doff = 0;
3947 size_t len = smb_len_large(inbuf);
3949 if (is_encrypted_packet(inbuf)) {
3950 /* Can't do this on encrypted
3955 if (CVAL(inbuf,smb_com) != SMBwriteX) {
3959 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
3960 CVAL(inbuf,smb_wct) != 14) {
3961 DEBUG(10,("is_valid_writeX_buffer: chained or "
3962 "invalid word length.\n"));
3966 conn = conn_find(SVAL(inbuf, smb_tid));
3968 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
3972 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
3975 if (IS_PRINT(conn)) {
3976 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
3979 doff = SVAL(inbuf,smb_vwv11);
3981 numtowrite = SVAL(inbuf,smb_vwv10);
3983 if (len > doff && len - doff > 0xFFFF) {
3984 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
3987 if (numtowrite == 0) {
3988 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
3992 /* Ensure the sizes match up. */
3993 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
3994 /* no pad byte...old smbclient :-( */
3995 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
3997 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4001 if (len - doff != numtowrite) {
4002 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4003 "len = %u, doff = %u, numtowrite = %u\n",
4006 (unsigned int)numtowrite ));
4010 DEBUG(10,("is_valid_writeX_buffer: true "
4011 "len = %u, doff = %u, numtowrite = %u\n",
4014 (unsigned int)numtowrite ));
4019 /****************************************************************************
4020 Reply to a write and X.
4021 ****************************************************************************/
4023 void reply_write_and_X(struct smb_request *req)
4025 connection_struct *conn = req->conn;
4031 unsigned int smb_doff;
4032 unsigned int smblen;
4036 START_PROFILE(SMBwriteX);
4038 if ((req->wct != 12) && (req->wct != 14)) {
4039 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4040 END_PROFILE(SMBwriteX);
4044 numtowrite = SVAL(req->vwv+10, 0);
4045 smb_doff = SVAL(req->vwv+11, 0);
4046 smblen = smb_len(req->inbuf);
4048 if (req->unread_bytes > 0xFFFF ||
4049 (smblen > smb_doff &&
4050 smblen - smb_doff > 0xFFFF)) {
4051 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4054 if (req->unread_bytes) {
4055 /* Can't do a recvfile write on IPC$ */
4057 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4058 END_PROFILE(SMBwriteX);
4061 if (numtowrite != req->unread_bytes) {
4062 reply_doserror(req, ERRDOS, ERRbadmem);
4063 END_PROFILE(SMBwriteX);
4067 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4068 smb_doff + numtowrite > smblen) {
4069 reply_doserror(req, ERRDOS, ERRbadmem);
4070 END_PROFILE(SMBwriteX);
4075 /* If it's an IPC, pass off the pipe handler. */
4077 if (req->unread_bytes) {
4078 reply_doserror(req, ERRDOS, ERRbadmem);
4079 END_PROFILE(SMBwriteX);
4082 reply_pipe_write_and_X(req);
4083 END_PROFILE(SMBwriteX);
4087 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4088 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4089 write_through = BITSETW(req->vwv+7,0);
4091 if (!check_fsp(conn, req, fsp)) {
4092 END_PROFILE(SMBwriteX);
4096 if (!CHECK_WRITE(fsp)) {
4097 reply_doserror(req, ERRDOS, ERRbadaccess);
4098 END_PROFILE(SMBwriteX);
4102 data = smb_base(req->inbuf) + smb_doff;
4104 if(req->wct == 14) {
4105 #ifdef LARGE_SMB_OFF_T
4107 * This is a large offset (64 bit) write.
4109 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4111 #else /* !LARGE_SMB_OFF_T */
4114 * Ensure we haven't been sent a >32 bit offset.
4117 if(IVAL(req->vwv+12, 0) != 0) {
4118 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4119 "used and we don't support 64 bit offsets.\n",
4120 (unsigned int)IVAL(req->vwv+12, 0) ));
4121 reply_doserror(req, ERRDOS, ERRbadaccess);
4122 END_PROFILE(SMBwriteX);
4126 #endif /* LARGE_SMB_OFF_T */
4129 if (is_locked(fsp,(uint32)req->smbpid,
4130 (uint64_t)numtowrite,
4131 (uint64_t)startpos, WRITE_LOCK)) {
4132 reply_doserror(req, ERRDOS, ERRlock);
4133 END_PROFILE(SMBwriteX);
4137 /* X/Open SMB protocol says that, unlike SMBwrite
4138 if the length is zero then NO truncation is
4139 done, just a write of zero. To truncate a file,
4142 if(numtowrite == 0) {
4146 if ((req->unread_bytes == 0) &&
4147 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4149 END_PROFILE(SMBwriteX);
4153 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4156 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4157 reply_unixerror(req, ERRHRD, ERRdiskfull);
4158 END_PROFILE(SMBwriteX);
4162 reply_outbuf(req, 6, 0);
4163 SSVAL(req->outbuf,smb_vwv2,nwritten);
4164 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4166 if (nwritten < (ssize_t)numtowrite) {
4167 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4168 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4171 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4172 fsp->fnum, (int)numtowrite, (int)nwritten));
4174 status = sync_file(conn, fsp, write_through);
4175 if (!NT_STATUS_IS_OK(status)) {
4176 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4177 fsp->fsp_name, nt_errstr(status) ));
4178 reply_nterror(req, status);
4179 END_PROFILE(SMBwriteX);
4183 END_PROFILE(SMBwriteX);
4188 /****************************************************************************
4190 ****************************************************************************/
4192 void reply_lseek(struct smb_request *req)
4194 connection_struct *conn = req->conn;
4200 START_PROFILE(SMBlseek);
4203 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4204 END_PROFILE(SMBlseek);
4208 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4210 if (!check_fsp(conn, req, fsp)) {
4214 flush_write_cache(fsp, SEEK_FLUSH);
4216 mode = SVAL(req->vwv+1, 0) & 3;
4217 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4218 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4227 res = fsp->fh->pos + startpos;
4238 if (umode == SEEK_END) {
4239 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4240 if(errno == EINVAL) {
4241 SMB_OFF_T current_pos = startpos;
4242 SMB_STRUCT_STAT sbuf;
4244 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4245 reply_unixerror(req, ERRDOS,
4247 END_PROFILE(SMBlseek);
4251 current_pos += sbuf.st_size;
4253 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4258 reply_unixerror(req, ERRDOS, ERRnoaccess);
4259 END_PROFILE(SMBlseek);
4266 reply_outbuf(req, 2, 0);
4267 SIVAL(req->outbuf,smb_vwv0,res);
4269 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4270 fsp->fnum, (double)startpos, (double)res, mode));
4272 END_PROFILE(SMBlseek);
4276 /****************************************************************************
4278 ****************************************************************************/
4280 void reply_flush(struct smb_request *req)
4282 connection_struct *conn = req->conn;
4286 START_PROFILE(SMBflush);
4289 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4293 fnum = SVAL(req->vwv+0, 0);
4294 fsp = file_fsp(req, fnum);
4296 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4301 file_sync_all(conn);
4303 NTSTATUS status = sync_file(conn, fsp, True);
4304 if (!NT_STATUS_IS_OK(status)) {
4305 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4306 fsp->fsp_name, nt_errstr(status) ));
4307 reply_nterror(req, status);
4308 END_PROFILE(SMBflush);
4313 reply_outbuf(req, 0, 0);
4315 DEBUG(3,("flush\n"));
4316 END_PROFILE(SMBflush);
4320 /****************************************************************************
4322 conn POINTER CAN BE NULL HERE !
4323 ****************************************************************************/
4325 void reply_exit(struct smb_request *req)
4327 START_PROFILE(SMBexit);
4329 file_close_pid(req->smbpid, req->vuid);
4331 reply_outbuf(req, 0, 0);
4333 DEBUG(3,("exit\n"));
4335 END_PROFILE(SMBexit);
4339 /****************************************************************************
4340 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4341 ****************************************************************************/
4343 void reply_close(struct smb_request *req)
4345 connection_struct *conn = req->conn;
4346 NTSTATUS status = NT_STATUS_OK;
4347 files_struct *fsp = NULL;
4348 START_PROFILE(SMBclose);
4351 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4352 END_PROFILE(SMBclose);
4356 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4359 * We can only use check_fsp if we know it's not a directory.
4362 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4363 reply_doserror(req, ERRDOS, ERRbadfid);
4364 END_PROFILE(SMBclose);
4368 if(fsp->is_directory) {
4370 * Special case - close NT SMB directory handle.
4372 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4373 status = close_file(req, fsp, NORMAL_CLOSE);
4377 * Close ordinary file.
4380 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4381 fsp->fh->fd, fsp->fnum,
4382 conn->num_files_open));
4385 * Take care of any time sent in the close.
4388 t = srv_make_unix_date3(req->vwv+1);
4389 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4392 * close_file() returns the unix errno if an error
4393 * was detected on close - normally this is due to
4394 * a disk full error. If not then it was probably an I/O error.
4397 status = close_file(req, fsp, NORMAL_CLOSE);
4400 if (!NT_STATUS_IS_OK(status)) {
4401 reply_nterror(req, status);
4402 END_PROFILE(SMBclose);
4406 reply_outbuf(req, 0, 0);
4407 END_PROFILE(SMBclose);
4411 /****************************************************************************
4412 Reply to a writeclose (Core+ protocol).
4413 ****************************************************************************/
4415 void reply_writeclose(struct smb_request *req)
4417 connection_struct *conn = req->conn;
4419 ssize_t nwritten = -1;
4420 NTSTATUS close_status = NT_STATUS_OK;
4423 struct timespec mtime;
4426 START_PROFILE(SMBwriteclose);
4429 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4430 END_PROFILE(SMBwriteclose);
4434 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4436 if (!check_fsp(conn, req, fsp)) {
4437 END_PROFILE(SMBwriteclose);
4440 if (!CHECK_WRITE(fsp)) {
4441 reply_doserror(req, ERRDOS,ERRbadaccess);
4442 END_PROFILE(SMBwriteclose);
4446 numtowrite = SVAL(req->vwv+1, 0);
4447 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4448 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4449 data = (const char *)req->buf + 1;
4452 && is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
4453 (uint64_t)startpos, WRITE_LOCK)) {
4454 reply_doserror(req, ERRDOS,ERRlock);
4455 END_PROFILE(SMBwriteclose);
4459 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4461 set_close_write_time(fsp, mtime);
4464 * More insanity. W2K only closes the file if writelen > 0.
4469 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4471 close_status = close_file(req, fsp, NORMAL_CLOSE);
4474 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4475 fsp->fnum, (int)numtowrite, (int)nwritten,
4476 conn->num_files_open));
4478 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4479 reply_doserror(req, ERRHRD, ERRdiskfull);
4480 END_PROFILE(SMBwriteclose);
4484 if(!NT_STATUS_IS_OK(close_status)) {
4485 reply_nterror(req, close_status);
4486 END_PROFILE(SMBwriteclose);
4490 reply_outbuf(req, 1, 0);
4492 SSVAL(req->outbuf,smb_vwv0,nwritten);
4493 END_PROFILE(SMBwriteclose);
4498 #define DBGC_CLASS DBGC_LOCKING
4500 /****************************************************************************
4502 ****************************************************************************/
4504 void reply_lock(struct smb_request *req)
4506 connection_struct *conn = req->conn;
4507 uint64_t count,offset;
4510 struct byte_range_lock *br_lck = NULL;
4512 START_PROFILE(SMBlock);
4515 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4516 END_PROFILE(SMBlock);
4520 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4522 if (!check_fsp(conn, req, fsp)) {
4523 END_PROFILE(SMBlock);
4527 count = (uint64_t)IVAL(req->vwv+1, 0);
4528 offset = (uint64_t)IVAL(req->vwv+3, 0);
4530 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4531 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4533 br_lck = do_lock(smbd_messaging_context(),
4540 False, /* Non-blocking lock. */
4545 TALLOC_FREE(br_lck);
4547 if (NT_STATUS_V(status)) {
4548 reply_nterror(req, status);
4549 END_PROFILE(SMBlock);
4553 reply_outbuf(req, 0, 0);
4555 END_PROFILE(SMBlock);
4559 /****************************************************************************
4561 ****************************************************************************/
4563 void reply_unlock(struct smb_request *req)
4565 connection_struct *conn = req->conn;
4566 uint64_t count,offset;
4570 START_PROFILE(SMBunlock);
4573 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4574 END_PROFILE(SMBunlock);
4578 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4580 if (!check_fsp(conn, req, fsp)) {
4581 END_PROFILE(SMBunlock);
4585 count = (uint64_t)IVAL(req->vwv+1, 0);
4586 offset = (uint64_t)IVAL(req->vwv+3, 0);
4588 status = do_unlock(smbd_messaging_context(),
4595 if (NT_STATUS_V(status)) {
4596 reply_nterror(req, status);
4597 END_PROFILE(SMBunlock);
4601 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4602 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4604 reply_outbuf(req, 0, 0);
4606 END_PROFILE(SMBunlock);
4611 #define DBGC_CLASS DBGC_ALL
4613 /****************************************************************************
4615 conn POINTER CAN BE NULL HERE !
4616 ****************************************************************************/
4618 void reply_tdis(struct smb_request *req)
4620 connection_struct *conn = req->conn;
4621 START_PROFILE(SMBtdis);
4624 DEBUG(4,("Invalid connection in tdis\n"));
4625 reply_doserror(req, ERRSRV, ERRinvnid);
4626 END_PROFILE(SMBtdis);
4632 close_cnum(conn,req->vuid);
4635 reply_outbuf(req, 0, 0);
4636 END_PROFILE(SMBtdis);
4640 /****************************************************************************
4642 conn POINTER CAN BE NULL HERE !
4643 ****************************************************************************/
4645 void reply_echo(struct smb_request *req)
4647 connection_struct *conn = req->conn;
4648 struct smb_perfcount_data local_pcd;
4649 struct smb_perfcount_data *cur_pcd;
4653 START_PROFILE(SMBecho);
4655 smb_init_perfcount_data(&local_pcd);
4658 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4659 END_PROFILE(SMBecho);
4663 smb_reverb = SVAL(req->vwv+0, 0);
4665 reply_outbuf(req, 1, req->buflen);
4667 /* copy any incoming data back out */
4668 if (req->buflen > 0) {
4669 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4672 if (smb_reverb > 100) {
4673 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4677 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4679 /* this makes sure we catch the request pcd */
4680 if (seq_num == smb_reverb) {
4681 cur_pcd = &req->pcd;
4683 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4684 cur_pcd = &local_pcd;
4687 SSVAL(req->outbuf,smb_vwv0,seq_num);
4689 show_msg((char *)req->outbuf);
4690 if (!srv_send_smb(smbd_server_fd(),
4691 (char *)req->outbuf,
4692 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4694 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4697 DEBUG(3,("echo %d times\n", smb_reverb));
4699 TALLOC_FREE(req->outbuf);
4701 END_PROFILE(SMBecho);
4705 /****************************************************************************
4706 Reply to a printopen.
4707 ****************************************************************************/
4709 void reply_printopen(struct smb_request *req)
4711 connection_struct *conn = req->conn;
4713 SMB_STRUCT_STAT sbuf;
4716 START_PROFILE(SMBsplopen);
4719 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4720 END_PROFILE(SMBsplopen);
4724 if (!CAN_PRINT(conn)) {
4725 reply_doserror(req, ERRDOS, ERRnoaccess);
4726 END_PROFILE(SMBsplopen);
4730 status = file_new(req, conn, &fsp);
4731 if(!NT_STATUS_IS_OK(status)) {
4732 reply_nterror(req, status);
4733 END_PROFILE(SMBsplopen);
4737 /* Open for exclusive use, write only. */
4738 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4740 if (!NT_STATUS_IS_OK(status)) {
4741 reply_nterror(req, status);
4742 END_PROFILE(SMBsplopen);
4746 reply_outbuf(req, 1, 0);
4747 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4749 DEBUG(3,("openprint fd=%d fnum=%d\n",
4750 fsp->fh->fd, fsp->fnum));
4752 END_PROFILE(SMBsplopen);
4756 /****************************************************************************
4757 Reply to a printclose.
4758 ****************************************************************************/
4760 void reply_printclose(struct smb_request *req)
4762 connection_struct *conn = req->conn;
4766 START_PROFILE(SMBsplclose);
4769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4770 END_PROFILE(SMBsplclose);
4774 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4776 if (!check_fsp(conn, req, fsp)) {
4777 END_PROFILE(SMBsplclose);
4781 if (!CAN_PRINT(conn)) {
4782 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4783 END_PROFILE(SMBsplclose);
4787 DEBUG(3,("printclose fd=%d fnum=%d\n",
4788 fsp->fh->fd,fsp->fnum));
4790 status = close_file(req, fsp, NORMAL_CLOSE);
4792 if(!NT_STATUS_IS_OK(status)) {
4793 reply_nterror(req, status);
4794 END_PROFILE(SMBsplclose);
4798 reply_outbuf(req, 0, 0);
4800 END_PROFILE(SMBsplclose);
4804 /****************************************************************************
4805 Reply to a printqueue.
4806 ****************************************************************************/
4808 void reply_printqueue(struct smb_request *req)
4810 connection_struct *conn = req->conn;
4814 START_PROFILE(SMBsplretq);
4817 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4818 END_PROFILE(SMBsplretq);
4822 max_count = SVAL(req->vwv+0, 0);
4823 start_index = SVAL(req->vwv+1, 0);
4825 /* we used to allow the client to get the cnum wrong, but that
4826 is really quite gross and only worked when there was only
4827 one printer - I think we should now only accept it if they
4828 get it right (tridge) */
4829 if (!CAN_PRINT(conn)) {
4830 reply_doserror(req, ERRDOS, ERRnoaccess);
4831 END_PROFILE(SMBsplretq);
4835 reply_outbuf(req, 2, 3);
4836 SSVAL(req->outbuf,smb_vwv0,0);
4837 SSVAL(req->outbuf,smb_vwv1,0);
4838 SCVAL(smb_buf(req->outbuf),0,1);
4839 SSVAL(smb_buf(req->outbuf),1,0);
4841 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4842 start_index, max_count));
4845 print_queue_struct *queue = NULL;
4846 print_status_struct status;
4847 int count = print_queue_status(SNUM(conn), &queue, &status);
4848 int num_to_get = ABS(max_count);
4849 int first = (max_count>0?start_index:start_index+max_count+1);
4855 num_to_get = MIN(num_to_get,count-first);
4858 for (i=first;i<first+num_to_get;i++) {
4862 srv_put_dos_date2(p,0,queue[i].time);
4863 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4864 SSVAL(p,5, queue[i].job);
4865 SIVAL(p,7,queue[i].size);
4867 srvstr_push(blob, req->flags2, p+12,
4868 queue[i].fs_user, 16, STR_ASCII);
4870 if (message_push_blob(
4873 blob, sizeof(blob))) == -1) {
4874 reply_nterror(req, NT_STATUS_NO_MEMORY);
4875 END_PROFILE(SMBsplretq);
4881 SSVAL(req->outbuf,smb_vwv0,count);
4882 SSVAL(req->outbuf,smb_vwv1,
4883 (max_count>0?first+count:first-1));
4884 SCVAL(smb_buf(req->outbuf),0,1);
4885 SSVAL(smb_buf(req->outbuf),1,28*count);
4890 DEBUG(3,("%d entries returned in queue\n",count));
4893 END_PROFILE(SMBsplretq);
4897 /****************************************************************************
4898 Reply to a printwrite.
4899 ****************************************************************************/
4901 void reply_printwrite(struct smb_request *req)
4903 connection_struct *conn = req->conn;
4908 START_PROFILE(SMBsplwr);
4911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4912 END_PROFILE(SMBsplwr);
4916 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4918 if (!check_fsp(conn, req, fsp)) {
4919 END_PROFILE(SMBsplwr);
4923 if (!CAN_PRINT(conn)) {
4924 reply_doserror(req, ERRDOS, ERRnoaccess);
4925 END_PROFILE(SMBsplwr);
4929 if (!CHECK_WRITE(fsp)) {
4930 reply_doserror(req, ERRDOS, ERRbadaccess);
4931 END_PROFILE(SMBsplwr);
4935 numtowrite = SVAL(req->buf, 1);
4937 if (req->buflen < numtowrite + 3) {
4938 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4939 END_PROFILE(SMBsplwr);
4943 data = (const char *)req->buf + 3;
4945 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
4946 reply_unixerror(req, ERRHRD, ERRdiskfull);
4947 END_PROFILE(SMBsplwr);
4951 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4953 END_PROFILE(SMBsplwr);
4957 /****************************************************************************
4959 ****************************************************************************/
4961 void reply_mkdir(struct smb_request *req)
4963 connection_struct *conn = req->conn;
4964 char *directory = NULL;
4966 SMB_STRUCT_STAT sbuf;
4967 TALLOC_CTX *ctx = talloc_tos();
4969 START_PROFILE(SMBmkdir);
4971 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
4972 STR_TERMINATE, &status);
4973 if (!NT_STATUS_IS_OK(status)) {
4974 reply_nterror(req, status);
4975 END_PROFILE(SMBmkdir);
4979 status = resolve_dfspath(ctx, conn,
4980 req->flags2 & FLAGS2_DFS_PATHNAMES,
4983 if (!NT_STATUS_IS_OK(status)) {
4984 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4985 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4986 ERRSRV, ERRbadpath);
4987 END_PROFILE(SMBmkdir);
4990 reply_nterror(req, status);
4991 END_PROFILE(SMBmkdir);
4995 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
4996 if (!NT_STATUS_IS_OK(status)) {
4997 reply_nterror(req, status);
4998 END_PROFILE(SMBmkdir);
5002 status = check_name(conn, directory);
5003 if (!NT_STATUS_IS_OK(status)) {
5004 reply_nterror(req, status);
5005 END_PROFILE(SMBmkdir);
5009 status = create_directory(conn, req, directory);
5011 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5013 if (!NT_STATUS_IS_OK(status)) {
5015 if (!use_nt_status()
5016 && NT_STATUS_EQUAL(status,
5017 NT_STATUS_OBJECT_NAME_COLLISION)) {
5019 * Yes, in the DOS error code case we get a
5020 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5021 * samba4 torture test.
5023 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5026 reply_nterror(req, status);
5027 END_PROFILE(SMBmkdir);
5031 reply_outbuf(req, 0, 0);
5033 DEBUG( 3, ( "mkdir %s\n", directory ) );
5035 END_PROFILE(SMBmkdir);
5039 /****************************************************************************
5040 Static function used by reply_rmdir to delete an entire directory
5041 tree recursively. Return True on ok, False on fail.
5042 ****************************************************************************/
5044 static bool recursive_rmdir(TALLOC_CTX *ctx,
5045 connection_struct *conn,
5048 const char *dname = NULL;
5052 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5058 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5059 char *fullname = NULL;
5061 if (ISDOT(dname) || ISDOTDOT(dname)) {
5065 if (!is_visible_file(conn, directory, dname, &st, False)) {
5069 /* Construct the full name. */
5070 fullname = talloc_asprintf(ctx,
5080 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5085 if(st.st_mode & S_IFDIR) {
5086 if(!recursive_rmdir(ctx, conn, fullname)) {
5090 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5094 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5098 TALLOC_FREE(fullname);
5100 TALLOC_FREE(dir_hnd);
5104 /****************************************************************************
5105 The internals of the rmdir code - called elsewhere.
5106 ****************************************************************************/
5108 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5109 connection_struct *conn,
5110 const char *directory)
5115 /* Might be a symlink. */
5116 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5117 return map_nt_error_from_unix(errno);
5120 if (S_ISLNK(st.st_mode)) {
5121 /* Is what it points to a directory ? */
5122 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5123 return map_nt_error_from_unix(errno);
5125 if (!(S_ISDIR(st.st_mode))) {
5126 return NT_STATUS_NOT_A_DIRECTORY;
5128 ret = SMB_VFS_UNLINK(conn,directory);
5130 ret = SMB_VFS_RMDIR(conn,directory);
5133 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5134 FILE_NOTIFY_CHANGE_DIR_NAME,
5136 return NT_STATUS_OK;
5139 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5141 * Check to see if the only thing in this directory are
5142 * vetoed files/directories. If so then delete them and
5143 * retry. If we fail to delete any of them (and we *don't*
5144 * do a recursive delete) then fail the rmdir.
5148 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5149 directory, NULL, 0);
5151 if(dir_hnd == NULL) {
5156 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5157 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5159 if (!is_visible_file(conn, directory, dname, &st, False))
5161 if(!IS_VETO_PATH(conn, dname)) {
5162 TALLOC_FREE(dir_hnd);
5168 /* We only have veto files/directories.
5169 * Are we allowed to delete them ? */
5171 if(!lp_recursive_veto_delete(SNUM(conn))) {
5172 TALLOC_FREE(dir_hnd);
5177 /* Do a recursive delete. */
5178 RewindDir(dir_hnd,&dirpos);
5179 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5180 char *fullname = NULL;
5182 if (ISDOT(dname) || ISDOTDOT(dname)) {
5185 if (!is_visible_file(conn, directory, dname, &st, False)) {
5189 fullname = talloc_asprintf(ctx,
5199 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5202 if(st.st_mode & S_IFDIR) {
5203 if(!recursive_rmdir(ctx, conn, fullname)) {
5206 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5209 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5212 TALLOC_FREE(fullname);
5214 TALLOC_FREE(dir_hnd);
5215 /* Retry the rmdir */
5216 ret = SMB_VFS_RMDIR(conn,directory);
5222 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5223 "%s\n", directory,strerror(errno)));
5224 return map_nt_error_from_unix(errno);
5227 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5228 FILE_NOTIFY_CHANGE_DIR_NAME,
5231 return NT_STATUS_OK;
5234 /****************************************************************************
5236 ****************************************************************************/
5238 void reply_rmdir(struct smb_request *req)
5240 connection_struct *conn = req->conn;
5241 char *directory = NULL;
5242 SMB_STRUCT_STAT sbuf;
5244 TALLOC_CTX *ctx = talloc_tos();
5246 START_PROFILE(SMBrmdir);
5248 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5249 STR_TERMINATE, &status);
5250 if (!NT_STATUS_IS_OK(status)) {
5251 reply_nterror(req, status);
5252 END_PROFILE(SMBrmdir);
5256 status = resolve_dfspath(ctx, conn,
5257 req->flags2 & FLAGS2_DFS_PATHNAMES,
5260 if (!NT_STATUS_IS_OK(status)) {
5261 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5262 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5263 ERRSRV, ERRbadpath);
5264 END_PROFILE(SMBrmdir);
5267 reply_nterror(req, status);
5268 END_PROFILE(SMBrmdir);
5272 status = unix_convert(ctx, conn, directory, False, &directory,
5274 if (!NT_STATUS_IS_OK(status)) {
5275 reply_nterror(req, status);
5276 END_PROFILE(SMBrmdir);
5280 status = check_name(conn, directory);
5281 if (!NT_STATUS_IS_OK(status)) {
5282 reply_nterror(req, status);
5283 END_PROFILE(SMBrmdir);
5287 dptr_closepath(directory, req->smbpid);
5288 status = rmdir_internals(ctx, conn, directory);
5289 if (!NT_STATUS_IS_OK(status)) {
5290 reply_nterror(req, status);
5291 END_PROFILE(SMBrmdir);
5295 reply_outbuf(req, 0, 0);
5297 DEBUG( 3, ( "rmdir %s\n", directory ) );
5299 END_PROFILE(SMBrmdir);
5303 /*******************************************************************
5304 Resolve wildcards in a filename rename.
5305 ********************************************************************/
5307 static bool resolve_wildcards(TALLOC_CTX *ctx,
5312 char *name2_copy = NULL;
5317 char *p,*p2, *pname1, *pname2;
5319 name2_copy = talloc_strdup(ctx, name2);
5324 pname1 = strrchr_m(name1,'/');
5325 pname2 = strrchr_m(name2_copy,'/');
5327 if (!pname1 || !pname2) {
5331 /* Truncate the copy of name2 at the last '/' */
5334 /* Now go past the '/' */
5338 root1 = talloc_strdup(ctx, pname1);
5339 root2 = talloc_strdup(ctx, pname2);
5341 if (!root1 || !root2) {
5345 p = strrchr_m(root1,'.');
5348 ext1 = talloc_strdup(ctx, p+1);
5350 ext1 = talloc_strdup(ctx, "");
5352 p = strrchr_m(root2,'.');
5355 ext2 = talloc_strdup(ctx, p+1);
5357 ext2 = talloc_strdup(ctx, "");
5360 if (!ext1 || !ext2) {
5368 /* Hmmm. Should this be mb-aware ? */
5371 } else if (*p2 == '*') {
5373 root2 = talloc_asprintf(ctx, "%s%s",
5392 /* Hmmm. Should this be mb-aware ? */
5395 } else if (*p2 == '*') {
5397 ext2 = talloc_asprintf(ctx, "%s%s",
5413 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5418 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5430 /****************************************************************************
5431 Ensure open files have their names updated. Updated to notify other smbd's
5433 ****************************************************************************/
5435 static void rename_open_files(connection_struct *conn,
5436 struct share_mode_lock *lck,
5437 const char *newname)
5440 bool did_rename = False;
5442 for(fsp = file_find_di_first(lck->id); fsp;
5443 fsp = file_find_di_next(fsp)) {
5444 /* fsp_name is a relative path under the fsp. To change this for other
5445 sharepaths we need to manipulate relative paths. */
5446 /* TODO - create the absolute path and manipulate the newname
5447 relative to the sharepath. */
5448 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5451 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5452 fsp->fnum, file_id_string_tos(&fsp->file_id),
5453 fsp->fsp_name, newname ));
5454 string_set(&fsp->fsp_name, newname);
5459 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5460 file_id_string_tos(&lck->id), newname ));
5463 /* Send messages to all smbd's (not ourself) that the name has changed. */
5464 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5468 /****************************************************************************
5469 We need to check if the source path is a parent directory of the destination
5470 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5471 refuse the rename with a sharing violation. Under UNIX the above call can
5472 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5473 probably need to check that the client is a Windows one before disallowing
5474 this as a UNIX client (one with UNIX extensions) can know the source is a
5475 symlink and make this decision intelligently. Found by an excellent bug
5476 report from <AndyLiebman@aol.com>.
5477 ****************************************************************************/
5479 static bool rename_path_prefix_equal(const char *src, const char *dest)
5481 const char *psrc = src;
5482 const char *pdst = dest;
5485 if (psrc[0] == '.' && psrc[1] == '/') {
5488 if (pdst[0] == '.' && pdst[1] == '/') {
5491 if ((slen = strlen(psrc)) > strlen(pdst)) {
5494 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5498 * Do the notify calls from a rename
5501 static void notify_rename(connection_struct *conn, bool is_dir,
5502 const char *oldpath, const char *newpath)
5504 char *olddir, *newdir;
5505 const char *oldname, *newname;
5508 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5509 : FILE_NOTIFY_CHANGE_FILE_NAME;
5511 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5512 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5513 TALLOC_FREE(olddir);
5517 if (strcmp(olddir, newdir) == 0) {
5518 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5519 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5522 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5523 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5525 TALLOC_FREE(olddir);
5526 TALLOC_FREE(newdir);
5528 /* this is a strange one. w2k3 gives an additional event for
5529 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5530 files, but not directories */
5532 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5533 FILE_NOTIFY_CHANGE_ATTRIBUTES
5534 |FILE_NOTIFY_CHANGE_CREATION,
5539 /****************************************************************************
5540 Rename an open file - given an fsp.
5541 ****************************************************************************/
5543 NTSTATUS rename_internals_fsp(connection_struct *conn,
5546 const char *newname_last_component,
5548 bool replace_if_exists)
5550 TALLOC_CTX *ctx = talloc_tos();
5551 SMB_STRUCT_STAT sbuf, sbuf1;
5552 NTSTATUS status = NT_STATUS_OK;
5553 struct share_mode_lock *lck = NULL;
5554 bool dst_exists, old_is_stream, new_is_stream;
5558 status = check_name(conn, newname);
5559 if (!NT_STATUS_IS_OK(status)) {
5563 /* Ensure newname contains a '/' */
5564 if(strrchr_m(newname,'/') == 0) {
5565 newname = talloc_asprintf(ctx,
5569 return NT_STATUS_NO_MEMORY;
5574 * Check for special case with case preserving and not
5575 * case sensitive. If the old last component differs from the original
5576 * last component only by case, then we should allow
5577 * the rename (user is trying to change the case of the
5581 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5582 strequal(newname, fsp->fsp_name)) {
5584 char *newname_modified_last_component = NULL;
5587 * Get the last component of the modified name.
5588 * Note that we guarantee that newname contains a '/'
5591 p = strrchr_m(newname,'/');
5592 newname_modified_last_component = talloc_strdup(ctx,
5594 if (!newname_modified_last_component) {
5595 return NT_STATUS_NO_MEMORY;
5598 if(strcsequal(newname_modified_last_component,
5599 newname_last_component) == False) {
5601 * Replace the modified last component with
5604 *p = '\0'; /* Truncate at the '/' */
5605 newname = talloc_asprintf(ctx,
5608 newname_last_component);
5613 * If the src and dest names are identical - including case,
5614 * don't do the rename, just return success.
5617 if (strcsequal(fsp->fsp_name, newname)) {
5618 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5620 return NT_STATUS_OK;
5623 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5624 new_is_stream = is_ntfs_stream_name(newname);
5626 /* Return the correct error code if both names aren't streams. */
5627 if (!old_is_stream && new_is_stream) {
5628 return NT_STATUS_OBJECT_NAME_INVALID;
5631 if (old_is_stream && !new_is_stream) {
5632 return NT_STATUS_INVALID_PARAMETER;
5636 * Have vfs_object_exist also fill sbuf1
5638 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5640 if(!replace_if_exists && dst_exists) {
5641 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5642 fsp->fsp_name,newname));
5643 return NT_STATUS_OBJECT_NAME_COLLISION;
5647 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5648 files_struct *dst_fsp = file_find_di_first(fileid);
5649 /* The file can be open when renaming a stream */
5650 if (dst_fsp && !new_is_stream) {
5651 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5652 return NT_STATUS_ACCESS_DENIED;
5656 /* Ensure we have a valid stat struct for the source. */
5657 if (fsp->fh->fd != -1) {
5658 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5659 return map_nt_error_from_unix(errno);
5663 if (fsp->posix_open) {
5664 ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
5666 ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
5669 return map_nt_error_from_unix(errno);
5673 status = can_rename(conn, fsp, attrs, &sbuf);
5675 if (!NT_STATUS_IS_OK(status)) {
5676 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5677 nt_errstr(status), fsp->fsp_name,newname));
5678 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5679 status = NT_STATUS_ACCESS_DENIED;
5683 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5684 return NT_STATUS_ACCESS_DENIED;
5687 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5691 * We have the file open ourselves, so not being able to get the
5692 * corresponding share mode lock is a fatal error.
5695 SMB_ASSERT(lck != NULL);
5697 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5698 uint32 create_options = fsp->fh->private_options;
5700 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5701 fsp->fsp_name,newname));
5703 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5705 rename_open_files(conn, lck, newname);
5708 * A rename acts as a new file create w.r.t. allowing an initial delete
5709 * on close, probably because in Windows there is a new handle to the
5710 * new file. If initial delete on close was requested but not
5711 * originally set, we need to set it here. This is probably not 100% correct,
5712 * but will work for the CIFSFS client which in non-posix mode
5713 * depends on these semantics. JRA.
5716 if (create_options & FILE_DELETE_ON_CLOSE) {
5717 status = can_set_delete_on_close(fsp, True, 0);
5719 if (NT_STATUS_IS_OK(status)) {
5720 /* Note that here we set the *inital* delete on close flag,
5721 * not the regular one. The magic gets handled in close. */
5722 fsp->initial_delete_on_close = True;
5726 return NT_STATUS_OK;
5731 if (errno == ENOTDIR || errno == EISDIR) {
5732 status = NT_STATUS_OBJECT_NAME_COLLISION;
5734 status = map_nt_error_from_unix(errno);
5737 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5738 nt_errstr(status), fsp->fsp_name,newname));
5743 /****************************************************************************
5744 The guts of the rename command, split out so it may be called by the NT SMB
5746 ****************************************************************************/
5748 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5749 connection_struct *conn,
5750 struct smb_request *req,
5751 const char *name_in,
5752 const char *newname_in,
5754 bool replace_if_exists,
5757 uint32_t access_mask)
5759 char *directory = NULL;
5761 char *last_component_src = NULL;
5762 char *last_component_dest = NULL;
5764 char *newname = NULL;
5767 NTSTATUS status = NT_STATUS_OK;
5768 SMB_STRUCT_STAT sbuf1, sbuf2;
5769 struct smb_Dir *dir_hnd = NULL;
5772 int create_options = 0;
5773 bool posix_pathnames = lp_posix_pathnames();
5778 status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5779 &last_component_src, &sbuf1);
5780 if (!NT_STATUS_IS_OK(status)) {
5784 status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5785 &last_component_dest, &sbuf2);
5786 if (!NT_STATUS_IS_OK(status)) {
5791 * Split the old name into directory and last component
5792 * strings. Note that unix_convert may have stripped off a
5793 * leading ./ from both name and newname if the rename is
5794 * at the root of the share. We need to make sure either both
5795 * name and newname contain a / character or neither of them do
5796 * as this is checked in resolve_wildcards().
5799 p = strrchr_m(name,'/');
5801 directory = talloc_strdup(ctx, ".");
5803 return NT_STATUS_NO_MEMORY;
5808 directory = talloc_strdup(ctx, name);
5810 return NT_STATUS_NO_MEMORY;
5813 *p = '/'; /* Replace needed for exceptional test below. */
5817 * We should only check the mangled cache
5818 * here if unix_convert failed. This means
5819 * that the path in 'mask' doesn't exist
5820 * on the file system and so we need to look
5821 * for a possible mangle. This patch from
5822 * Tine Smukavec <valentin.smukavec@hermes.si>.
5825 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5826 char *new_mask = NULL;
5827 mangle_lookup_name_from_8_3(ctx,
5836 if (!src_has_wild) {
5840 * No wildcards - just process the one file.
5842 bool is_short_name = mangle_is_8_3(name, True, conn->params);
5844 /* Add a terminating '/' to the directory name. */
5845 directory = talloc_asprintf_append(directory,
5849 return NT_STATUS_NO_MEMORY;
5852 /* Ensure newname contains a '/' also */
5853 if(strrchr_m(newname,'/') == 0) {
5854 newname = talloc_asprintf(ctx,
5858 return NT_STATUS_NO_MEMORY;
5862 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5863 "case_preserve = %d, short case preserve = %d, "
5864 "directory = %s, newname = %s, "
5865 "last_component_dest = %s, is_8_3 = %d\n",
5866 conn->case_sensitive, conn->case_preserve,
5867 conn->short_case_preserve, directory,
5868 newname, last_component_dest, is_short_name));
5870 /* The dest name still may have wildcards. */
5871 if (dest_has_wild) {
5872 char *mod_newname = NULL;
5873 if (!resolve_wildcards(ctx,
5874 directory,newname,&mod_newname)) {
5875 DEBUG(6, ("rename_internals: resolve_wildcards "
5879 return NT_STATUS_NO_MEMORY;
5881 newname = mod_newname;
5885 if (posix_pathnames) {
5886 SMB_VFS_LSTAT(conn, directory, &sbuf1);
5888 SMB_VFS_STAT(conn, directory, &sbuf1);
5891 if (S_ISDIR(sbuf1.st_mode)) {
5892 create_options |= FILE_DIRECTORY_FILE;
5895 status = SMB_VFS_CREATE_FILE(
5898 0, /* root_dir_fid */
5899 directory, /* fname */
5900 0, /* create_file_flags */
5901 access_mask, /* access_mask */
5902 (FILE_SHARE_READ | /* share_access */
5904 FILE_OPEN, /* create_disposition*/
5905 create_options, /* create_options */
5906 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
5907 0, /* oplock_request */
5908 0, /* allocation_size */
5913 &sbuf1); /* psbuf */
5915 if (!NT_STATUS_IS_OK(status)) {
5916 DEBUG(3, ("Could not open rename source %s: %s\n",
5917 directory, nt_errstr(status)));
5921 status = rename_internals_fsp(conn, fsp, newname,
5922 last_component_dest,
5923 attrs, replace_if_exists);
5925 close_file(req, fsp, NORMAL_CLOSE);
5927 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5928 nt_errstr(status), directory,newname));
5934 * Wildcards - process each file that matches.
5936 if (strequal(mask,"????????.???")) {
5941 status = check_name(conn, directory);
5942 if (!NT_STATUS_IS_OK(status)) {
5946 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
5947 if (dir_hnd == NULL) {
5948 return map_nt_error_from_unix(errno);
5951 status = NT_STATUS_NO_SUCH_FILE;
5953 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5954 * - gentest fix. JRA
5957 while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
5958 files_struct *fsp = NULL;
5960 char *destname = NULL;
5961 bool sysdir_entry = False;
5963 /* Quick check for "." and ".." */
5964 if (ISDOT(dname) || ISDOTDOT(dname)) {
5966 sysdir_entry = True;
5972 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5976 if(!mask_match(dname, mask, conn->case_sensitive)) {
5981 status = NT_STATUS_OBJECT_NAME_INVALID;
5985 fname = talloc_asprintf(ctx,
5990 return NT_STATUS_NO_MEMORY;
5993 if (!resolve_wildcards(ctx,
5994 fname,newname,&destname)) {
5995 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6001 return NT_STATUS_NO_MEMORY;
6005 if (posix_pathnames) {
6006 SMB_VFS_LSTAT(conn, fname, &sbuf1);
6008 SMB_VFS_STAT(conn, fname, &sbuf1);
6013 if (S_ISDIR(sbuf1.st_mode)) {
6014 create_options |= FILE_DIRECTORY_FILE;
6017 status = SMB_VFS_CREATE_FILE(
6020 0, /* root_dir_fid */
6022 0, /* create_file_flags */
6023 access_mask, /* access_mask */
6024 (FILE_SHARE_READ | /* share_access */
6026 FILE_OPEN, /* create_disposition*/
6027 create_options, /* create_options */
6028 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6029 0, /* oplock_request */
6030 0, /* allocation_size */
6035 &sbuf1); /* psbuf */
6037 if (!NT_STATUS_IS_OK(status)) {
6038 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6039 "returned %s rename %s -> %s\n",
6040 nt_errstr(status), directory, newname));
6044 status = rename_internals_fsp(conn, fsp, destname, dname,
6045 attrs, replace_if_exists);
6047 close_file(req, fsp, NORMAL_CLOSE);
6049 if (!NT_STATUS_IS_OK(status)) {
6050 DEBUG(3, ("rename_internals_fsp returned %s for "
6051 "rename %s -> %s\n", nt_errstr(status),
6052 directory, newname));
6058 DEBUG(3,("rename_internals: doing rename on %s -> "
6059 "%s\n",fname,destname));
6062 TALLOC_FREE(destname);
6064 TALLOC_FREE(dir_hnd);
6066 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6067 status = map_nt_error_from_unix(errno);
6073 /****************************************************************************
6075 ****************************************************************************/
6077 void reply_mv(struct smb_request *req)
6079 connection_struct *conn = req->conn;
6081 char *newname = NULL;
6085 bool src_has_wcard = False;
6086 bool dest_has_wcard = False;
6087 TALLOC_CTX *ctx = talloc_tos();
6089 START_PROFILE(SMBmv);
6092 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6097 attrs = SVAL(req->vwv+0, 0);
6099 p = (const char *)req->buf + 1;
6100 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6101 &status, &src_has_wcard);
6102 if (!NT_STATUS_IS_OK(status)) {
6103 reply_nterror(req, status);
6108 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6109 &status, &dest_has_wcard);
6110 if (!NT_STATUS_IS_OK(status)) {
6111 reply_nterror(req, status);
6116 status = resolve_dfspath_wcard(ctx, conn,
6117 req->flags2 & FLAGS2_DFS_PATHNAMES,
6121 if (!NT_STATUS_IS_OK(status)) {
6122 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6123 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6124 ERRSRV, ERRbadpath);
6128 reply_nterror(req, status);
6133 status = resolve_dfspath_wcard(ctx, conn,
6134 req->flags2 & FLAGS2_DFS_PATHNAMES,
6138 if (!NT_STATUS_IS_OK(status)) {
6139 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6140 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6141 ERRSRV, ERRbadpath);
6145 reply_nterror(req, status);
6150 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6152 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6153 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6154 if (!NT_STATUS_IS_OK(status)) {
6155 if (open_was_deferred(req->mid)) {
6156 /* We have re-scheduled this call. */
6160 reply_nterror(req, status);
6165 reply_outbuf(req, 0, 0);
6171 /*******************************************************************
6172 Copy a file as part of a reply_copy.
6173 ******************************************************************/
6176 * TODO: check error codes on all callers
6179 NTSTATUS copy_file(TALLOC_CTX *ctx,
6180 connection_struct *conn,
6185 bool target_is_directory)
6187 SMB_STRUCT_STAT src_sbuf, sbuf2;
6189 files_struct *fsp1,*fsp2;
6192 uint32 new_create_disposition;
6195 dest = talloc_strdup(ctx, dest1);
6197 return NT_STATUS_NO_MEMORY;
6199 if (target_is_directory) {
6200 const char *p = strrchr_m(src,'/');
6206 dest = talloc_asprintf_append(dest,
6210 return NT_STATUS_NO_MEMORY;
6214 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6216 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6219 if (!target_is_directory && count) {
6220 new_create_disposition = FILE_OPEN;
6222 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6223 NULL, NULL, &new_create_disposition, NULL)) {
6225 return NT_STATUS_INVALID_PARAMETER;
6229 status = SMB_VFS_CREATE_FILE(
6232 0, /* root_dir_fid */
6234 0, /* create_file_flags */
6235 FILE_GENERIC_READ, /* access_mask */
6236 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6237 FILE_OPEN, /* create_disposition*/
6238 0, /* create_options */
6239 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6240 INTERNAL_OPEN_ONLY, /* oplock_request */
6241 0, /* allocation_size */
6246 &src_sbuf); /* psbuf */
6248 if (!NT_STATUS_IS_OK(status)) {
6253 dosattrs = dos_mode(conn, src, &src_sbuf);
6254 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6255 ZERO_STRUCTP(&sbuf2);
6258 status = SMB_VFS_CREATE_FILE(
6261 0, /* root_dir_fid */
6263 0, /* create_file_flags */
6264 FILE_GENERIC_WRITE, /* access_mask */
6265 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6266 new_create_disposition, /* create_disposition*/
6267 0, /* create_options */
6268 dosattrs, /* file_attributes */
6269 INTERNAL_OPEN_ONLY, /* oplock_request */
6270 0, /* allocation_size */
6275 &sbuf2); /* psbuf */
6279 if (!NT_STATUS_IS_OK(status)) {
6280 close_file(NULL, fsp1, ERROR_CLOSE);
6284 if ((ofun&3) == 1) {
6285 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6286 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6288 * Stop the copy from occurring.
6291 src_sbuf.st_size = 0;
6295 if (src_sbuf.st_size) {
6296 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6299 close_file(NULL, fsp1, NORMAL_CLOSE);
6301 /* Ensure the modtime is set correctly on the destination file. */
6302 set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
6305 * As we are opening fsp1 read-only we only expect
6306 * an error on close on fsp2 if we are out of space.
6307 * Thus we don't look at the error return from the
6310 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6312 if (!NT_STATUS_IS_OK(status)) {
6316 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6317 return NT_STATUS_DISK_FULL;
6320 return NT_STATUS_OK;
6323 /****************************************************************************
6324 Reply to a file copy.
6325 ****************************************************************************/
6327 void reply_copy(struct smb_request *req)
6329 connection_struct *conn = req->conn;
6331 char *newname = NULL;
6332 char *directory = NULL;
6333 const char *mask = NULL;
6334 const char mask_star[] = "*";
6337 int error = ERRnoaccess;
6342 bool target_is_directory=False;
6343 bool source_has_wild = False;
6344 bool dest_has_wild = False;
6345 SMB_STRUCT_STAT sbuf1, sbuf2;
6347 TALLOC_CTX *ctx = talloc_tos();
6349 START_PROFILE(SMBcopy);
6352 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6353 END_PROFILE(SMBcopy);
6357 tid2 = SVAL(req->vwv+0, 0);
6358 ofun = SVAL(req->vwv+1, 0);
6359 flags = SVAL(req->vwv+2, 0);
6361 p = (const char *)req->buf;
6362 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6363 &status, &source_has_wild);
6364 if (!NT_STATUS_IS_OK(status)) {
6365 reply_nterror(req, status);
6366 END_PROFILE(SMBcopy);
6369 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6370 &status, &dest_has_wild);
6371 if (!NT_STATUS_IS_OK(status)) {
6372 reply_nterror(req, status);
6373 END_PROFILE(SMBcopy);
6377 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6379 if (tid2 != conn->cnum) {
6380 /* can't currently handle inter share copies XXXX */
6381 DEBUG(3,("Rejecting inter-share copy\n"));
6382 reply_doserror(req, ERRSRV, ERRinvdevice);
6383 END_PROFILE(SMBcopy);
6387 status = resolve_dfspath_wcard(ctx, conn,
6388 req->flags2 & FLAGS2_DFS_PATHNAMES,
6392 if (!NT_STATUS_IS_OK(status)) {
6393 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6394 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6395 ERRSRV, ERRbadpath);
6396 END_PROFILE(SMBcopy);
6399 reply_nterror(req, status);
6400 END_PROFILE(SMBcopy);
6404 status = resolve_dfspath_wcard(ctx, conn,
6405 req->flags2 & FLAGS2_DFS_PATHNAMES,
6409 if (!NT_STATUS_IS_OK(status)) {
6410 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6411 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6412 ERRSRV, ERRbadpath);
6413 END_PROFILE(SMBcopy);
6416 reply_nterror(req, status);
6417 END_PROFILE(SMBcopy);
6421 status = unix_convert(ctx, conn, name, source_has_wild,
6422 &name, NULL, &sbuf1);
6423 if (!NT_STATUS_IS_OK(status)) {
6424 reply_nterror(req, status);
6425 END_PROFILE(SMBcopy);
6429 status = unix_convert(ctx, conn, newname, dest_has_wild,
6430 &newname, NULL, &sbuf2);
6431 if (!NT_STATUS_IS_OK(status)) {
6432 reply_nterror(req, status);
6433 END_PROFILE(SMBcopy);
6437 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6439 if ((flags&1) && target_is_directory) {
6440 reply_doserror(req, ERRDOS, ERRbadfile);
6441 END_PROFILE(SMBcopy);
6445 if ((flags&2) && !target_is_directory) {
6446 reply_doserror(req, ERRDOS, ERRbadpath);
6447 END_PROFILE(SMBcopy);
6451 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6452 /* wants a tree copy! XXXX */
6453 DEBUG(3,("Rejecting tree copy\n"));
6454 reply_doserror(req, ERRSRV, ERRerror);
6455 END_PROFILE(SMBcopy);
6459 p = strrchr_m(name,'/');
6461 directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
6464 directory = talloc_strdup(ctx, "./");
6469 reply_nterror(req, NT_STATUS_NO_MEMORY);
6470 END_PROFILE(SMBcopy);
6475 * We should only check the mangled cache
6476 * here if unix_convert failed. This means
6477 * that the path in 'mask' doesn't exist
6478 * on the file system and so we need to look
6479 * for a possible mangle. This patch from
6480 * Tine Smukavec <valentin.smukavec@hermes.si>.
6483 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6484 char *new_mask = NULL;
6485 mangle_lookup_name_from_8_3(ctx,
6494 if (!source_has_wild) {
6495 directory = talloc_asprintf_append(directory,
6498 if (dest_has_wild) {
6499 char *mod_newname = NULL;
6500 if (!resolve_wildcards(ctx,
6501 directory,newname,&mod_newname)) {
6502 reply_nterror(req, NT_STATUS_NO_MEMORY);
6503 END_PROFILE(SMBcopy);
6506 newname = mod_newname;
6509 status = check_name(conn, directory);
6510 if (!NT_STATUS_IS_OK(status)) {
6511 reply_nterror(req, status);
6512 END_PROFILE(SMBcopy);
6516 status = check_name(conn, newname);
6517 if (!NT_STATUS_IS_OK(status)) {
6518 reply_nterror(req, status);
6519 END_PROFILE(SMBcopy);
6523 status = copy_file(ctx,conn,directory,newname,ofun,
6524 count,target_is_directory);
6526 if(!NT_STATUS_IS_OK(status)) {
6527 reply_nterror(req, status);
6528 END_PROFILE(SMBcopy);
6534 struct smb_Dir *dir_hnd = NULL;
6535 const char *dname = NULL;
6538 if (strequal(mask,"????????.???")) {
6542 status = check_name(conn, directory);
6543 if (!NT_STATUS_IS_OK(status)) {
6544 reply_nterror(req, status);
6545 END_PROFILE(SMBcopy);
6549 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6550 if (dir_hnd == NULL) {
6551 status = map_nt_error_from_unix(errno);
6552 reply_nterror(req, status);
6553 END_PROFILE(SMBcopy);
6559 while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
6560 char *destname = NULL;
6563 if (ISDOT(dname) || ISDOTDOT(dname)) {
6567 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6571 if(!mask_match(dname, mask, conn->case_sensitive)) {
6575 error = ERRnoaccess;
6576 fname = talloc_asprintf(ctx,
6581 TALLOC_FREE(dir_hnd);
6582 reply_nterror(req, NT_STATUS_NO_MEMORY);
6583 END_PROFILE(SMBcopy);
6587 if (!resolve_wildcards(ctx,
6588 fname,newname,&destname)) {
6592 TALLOC_FREE(dir_hnd);
6593 reply_nterror(req, NT_STATUS_NO_MEMORY);
6594 END_PROFILE(SMBcopy);
6598 status = check_name(conn, fname);
6599 if (!NT_STATUS_IS_OK(status)) {
6600 TALLOC_FREE(dir_hnd);
6601 reply_nterror(req, status);
6602 END_PROFILE(SMBcopy);
6606 status = check_name(conn, destname);
6607 if (!NT_STATUS_IS_OK(status)) {
6608 TALLOC_FREE(dir_hnd);
6609 reply_nterror(req, status);
6610 END_PROFILE(SMBcopy);
6614 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6616 status = copy_file(ctx,conn,fname,destname,ofun,
6617 count,target_is_directory);
6618 if (NT_STATUS_IS_OK(status)) {
6622 TALLOC_FREE(destname);
6624 TALLOC_FREE(dir_hnd);
6629 /* Error on close... */
6631 reply_unixerror(req, ERRHRD, ERRgeneral);
6632 END_PROFILE(SMBcopy);
6636 reply_doserror(req, ERRDOS, error);
6637 END_PROFILE(SMBcopy);
6641 reply_outbuf(req, 1, 0);
6642 SSVAL(req->outbuf,smb_vwv0,count);
6644 END_PROFILE(SMBcopy);
6649 #define DBGC_CLASS DBGC_LOCKING
6651 /****************************************************************************
6652 Get a lock pid, dealing with large count requests.
6653 ****************************************************************************/
6655 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6656 bool large_file_format)
6658 if(!large_file_format)
6659 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6661 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6664 /****************************************************************************
6665 Get a lock count, dealing with large count requests.
6666 ****************************************************************************/
6668 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6669 bool large_file_format)
6673 if(!large_file_format) {
6674 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6677 #if defined(HAVE_LONGLONG)
6678 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6679 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6680 #else /* HAVE_LONGLONG */
6683 * NT4.x seems to be broken in that it sends large file (64 bit)
6684 * lockingX calls even if the CAP_LARGE_FILES was *not*
6685 * negotiated. For boxes without large unsigned ints truncate the
6686 * lock count by dropping the top 32 bits.
6689 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6690 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6691 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6692 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6693 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6696 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6697 #endif /* HAVE_LONGLONG */
6703 #if !defined(HAVE_LONGLONG)
6704 /****************************************************************************
6705 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6706 ****************************************************************************/
6708 static uint32 map_lock_offset(uint32 high, uint32 low)
6712 uint32 highcopy = high;
6715 * Try and find out how many significant bits there are in high.
6718 for(i = 0; highcopy; i++)
6722 * We use 31 bits not 32 here as POSIX
6723 * lock offsets may not be negative.
6726 mask = (~0) << (31 - i);
6729 return 0; /* Fail. */
6735 #endif /* !defined(HAVE_LONGLONG) */
6737 /****************************************************************************
6738 Get a lock offset, dealing with large offset requests.
6739 ****************************************************************************/
6741 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6742 bool large_file_format, bool *err)
6744 uint64_t offset = 0;
6748 if(!large_file_format) {
6749 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6752 #if defined(HAVE_LONGLONG)
6753 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6754 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6755 #else /* HAVE_LONGLONG */
6758 * NT4.x seems to be broken in that it sends large file (64 bit)
6759 * lockingX calls even if the CAP_LARGE_FILES was *not*
6760 * negotiated. For boxes without large unsigned ints mangle the
6761 * lock offset by mapping the top 32 bits onto the lower 32.
6764 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6765 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6766 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6769 if((new_low = map_lock_offset(high, low)) == 0) {
6771 return (uint64_t)-1;
6774 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6775 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6776 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6777 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6780 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6781 #endif /* HAVE_LONGLONG */
6787 /****************************************************************************
6788 Reply to a lockingX request.
6789 ****************************************************************************/
6791 void reply_lockingX(struct smb_request *req)
6793 connection_struct *conn = req->conn;
6795 unsigned char locktype;
6796 unsigned char oplocklevel;
6799 uint64_t count = 0, offset = 0;
6803 const uint8_t *data;
6804 bool large_file_format;
6806 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6808 START_PROFILE(SMBlockingX);
6811 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6812 END_PROFILE(SMBlockingX);
6816 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
6817 locktype = CVAL(req->vwv+3, 0);
6818 oplocklevel = CVAL(req->vwv+3, 1);
6819 num_ulocks = SVAL(req->vwv+6, 0);
6820 num_locks = SVAL(req->vwv+7, 0);
6821 lock_timeout = IVAL(req->vwv+4, 0);
6822 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6824 if (!check_fsp(conn, req, fsp)) {
6825 END_PROFILE(SMBlockingX);
6831 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6832 /* we don't support these - and CANCEL_LOCK makes w2k
6833 and XP reboot so I don't really want to be
6834 compatible! (tridge) */
6835 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6836 END_PROFILE(SMBlockingX);
6840 /* Check if this is an oplock break on a file
6841 we have granted an oplock on.
6843 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6844 /* Client can insist on breaking to none. */
6845 bool break_to_none = (oplocklevel == 0);
6848 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6849 "for fnum = %d\n", (unsigned int)oplocklevel,
6853 * Make sure we have granted an exclusive or batch oplock on
6857 if (fsp->oplock_type == 0) {
6859 /* The Samba4 nbench simulator doesn't understand
6860 the difference between break to level2 and break
6861 to none from level2 - it sends oplock break
6862 replies in both cases. Don't keep logging an error
6863 message here - just ignore it. JRA. */
6865 DEBUG(5,("reply_lockingX: Error : oplock break from "
6866 "client for fnum = %d (oplock=%d) and no "
6867 "oplock granted on this file (%s).\n",
6868 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
6870 /* if this is a pure oplock break request then don't
6872 if (num_locks == 0 && num_ulocks == 0) {
6873 END_PROFILE(SMBlockingX);
6876 END_PROFILE(SMBlockingX);
6877 reply_doserror(req, ERRDOS, ERRlock);
6882 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6884 result = remove_oplock(fsp);
6886 result = downgrade_oplock(fsp);
6890 DEBUG(0, ("reply_lockingX: error in removing "
6891 "oplock on file %s\n", fsp->fsp_name));
6892 /* Hmmm. Is this panic justified? */
6893 smb_panic("internal tdb error");
6896 reply_to_oplock_break_requests(fsp);
6898 /* if this is a pure oplock break request then don't send a
6900 if (num_locks == 0 && num_ulocks == 0) {
6901 /* Sanity check - ensure a pure oplock break is not a
6903 if(CVAL(req->vwv+0, 0) != 0xff)
6904 DEBUG(0,("reply_lockingX: Error : pure oplock "
6905 "break is a chained %d request !\n",
6906 (unsigned int)CVAL(req->vwv+0, 0)));
6907 END_PROFILE(SMBlockingX);
6913 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6914 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6915 END_PROFILE(SMBlockingX);
6919 /* Data now points at the beginning of the list
6920 of smb_unlkrng structs */
6921 for(i = 0; i < (int)num_ulocks; i++) {
6922 lock_pid = get_lock_pid( data, i, large_file_format);
6923 count = get_lock_count( data, i, large_file_format);
6924 offset = get_lock_offset( data, i, large_file_format, &err);
6927 * There is no error code marked "stupid client bug".... :-).
6930 END_PROFILE(SMBlockingX);
6931 reply_doserror(req, ERRDOS, ERRnoaccess);
6935 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6936 "pid %u, file %s\n", (double)offset, (double)count,
6937 (unsigned int)lock_pid, fsp->fsp_name ));
6939 status = do_unlock(smbd_messaging_context(),
6946 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
6947 nt_errstr(status)));
6949 if (NT_STATUS_V(status)) {
6950 END_PROFILE(SMBlockingX);
6951 reply_nterror(req, status);
6956 /* Setup the timeout in seconds. */
6958 if (!lp_blocking_locks(SNUM(conn))) {
6962 /* Now do any requested locks */
6963 data += ((large_file_format ? 20 : 10)*num_ulocks);
6965 /* Data now points at the beginning of the list
6966 of smb_lkrng structs */
6968 for(i = 0; i < (int)num_locks; i++) {
6969 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
6970 READ_LOCK:WRITE_LOCK);
6971 lock_pid = get_lock_pid( data, i, large_file_format);
6972 count = get_lock_count( data, i, large_file_format);
6973 offset = get_lock_offset( data, i, large_file_format, &err);
6976 * There is no error code marked "stupid client bug".... :-).
6979 END_PROFILE(SMBlockingX);
6980 reply_doserror(req, ERRDOS, ERRnoaccess);
6984 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6985 "%u, file %s timeout = %d\n", (double)offset,
6986 (double)count, (unsigned int)lock_pid,
6987 fsp->fsp_name, (int)lock_timeout ));
6989 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6990 struct blocking_lock_record *blr = NULL;
6992 if (lp_blocking_locks(SNUM(conn))) {
6994 /* Schedule a message to ourselves to
6995 remove the blocking lock record and
6996 return the right error. */
6998 blr = blocking_lock_cancel(fsp,
7004 NT_STATUS_FILE_LOCK_CONFLICT);
7006 END_PROFILE(SMBlockingX);
7011 ERRcancelviolation));
7015 /* Remove a matching pending lock. */
7016 status = do_lock_cancel(fsp,
7023 bool blocking_lock = lock_timeout ? True : False;
7024 bool defer_lock = False;
7025 struct byte_range_lock *br_lck;
7026 uint32 block_smbpid;
7028 br_lck = do_lock(smbd_messaging_context(),
7040 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7041 /* Windows internal resolution for blocking locks seems
7042 to be about 200ms... Don't wait for less than that. JRA. */
7043 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7044 lock_timeout = lp_lock_spin_time();
7049 /* This heuristic seems to match W2K3 very well. If a
7050 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7051 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7052 far as I can tell. Replacement for do_lock_spin(). JRA. */
7054 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7055 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7057 lock_timeout = lp_lock_spin_time();
7060 if (br_lck && defer_lock) {
7062 * A blocking lock was requested. Package up
7063 * this smb into a queued request and push it
7064 * onto the blocking lock queue.
7066 if(push_blocking_lock_request(br_lck,
7077 TALLOC_FREE(br_lck);
7078 END_PROFILE(SMBlockingX);
7083 TALLOC_FREE(br_lck);
7086 if (NT_STATUS_V(status)) {
7087 END_PROFILE(SMBlockingX);
7088 reply_nterror(req, status);
7093 /* If any of the above locks failed, then we must unlock
7094 all of the previous locks (X/Open spec). */
7096 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7100 * Ensure we don't do a remove on the lock that just failed,
7101 * as under POSIX rules, if we have a lock already there, we
7102 * will delete it (and we shouldn't) .....
7104 for(i--; i >= 0; i--) {
7105 lock_pid = get_lock_pid( data, i, large_file_format);
7106 count = get_lock_count( data, i, large_file_format);
7107 offset = get_lock_offset( data, i, large_file_format,
7111 * There is no error code marked "stupid client
7115 END_PROFILE(SMBlockingX);
7116 reply_doserror(req, ERRDOS, ERRnoaccess);
7120 do_unlock(smbd_messaging_context(),
7127 END_PROFILE(SMBlockingX);
7128 reply_nterror(req, status);
7132 reply_outbuf(req, 2, 0);
7134 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7135 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7137 END_PROFILE(SMBlockingX);
7142 #define DBGC_CLASS DBGC_ALL
7144 /****************************************************************************
7145 Reply to a SMBreadbmpx (read block multiplex) request.
7146 Always reply with an error, if someone has a platform really needs this,
7147 please contact vl@samba.org
7148 ****************************************************************************/
7150 void reply_readbmpx(struct smb_request *req)
7152 START_PROFILE(SMBreadBmpx);
7153 reply_doserror(req, ERRSRV, ERRuseSTD);
7154 END_PROFILE(SMBreadBmpx);
7158 /****************************************************************************
7159 Reply to a SMBreadbs (read block multiplex secondary) request.
7160 Always reply with an error, if someone has a platform really needs this,
7161 please contact vl@samba.org
7162 ****************************************************************************/
7164 void reply_readbs(struct smb_request *req)
7166 START_PROFILE(SMBreadBs);
7167 reply_doserror(req, ERRSRV, ERRuseSTD);
7168 END_PROFILE(SMBreadBs);
7172 /****************************************************************************
7173 Reply to a SMBsetattrE.
7174 ****************************************************************************/
7176 void reply_setattrE(struct smb_request *req)
7178 connection_struct *conn = req->conn;
7179 struct smb_file_time ft;
7181 SMB_STRUCT_STAT sbuf;
7184 START_PROFILE(SMBsetattrE);
7188 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7189 END_PROFILE(SMBsetattrE);
7193 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7195 if(!fsp || (fsp->conn != conn)) {
7196 reply_doserror(req, ERRDOS, ERRbadfid);
7197 END_PROFILE(SMBsetattrE);
7203 * Convert the DOS times into unix times.
7206 ft.atime = convert_time_t_to_timespec(
7207 srv_make_unix_date2(req->vwv+3));
7208 ft.mtime = convert_time_t_to_timespec(
7209 srv_make_unix_date2(req->vwv+5));
7210 ft.create_time = convert_time_t_to_timespec(
7211 srv_make_unix_date2(req->vwv+1));
7213 reply_outbuf(req, 0, 0);
7216 * Patch from Ray Frush <frush@engr.colostate.edu>
7217 * Sometimes times are sent as zero - ignore them.
7220 /* Ensure we have a valid stat struct for the source. */
7221 if (fsp->fh->fd != -1) {
7222 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7223 status = map_nt_error_from_unix(errno);
7224 reply_nterror(req, status);
7225 END_PROFILE(SMBsetattrE);
7231 if (fsp->posix_open) {
7232 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
7234 ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
7237 status = map_nt_error_from_unix(errno);
7238 reply_nterror(req, status);
7239 END_PROFILE(SMBsetattrE);
7244 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7246 if (!NT_STATUS_IS_OK(status)) {
7247 reply_doserror(req, ERRDOS, ERRnoaccess);
7248 END_PROFILE(SMBsetattrE);
7252 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7255 (unsigned int)ft.atime.tv_sec,
7256 (unsigned int)ft.mtime.tv_sec,
7257 (unsigned int)ft.create_time.tv_sec
7260 END_PROFILE(SMBsetattrE);
7265 /* Back from the dead for OS/2..... JRA. */
7267 /****************************************************************************
7268 Reply to a SMBwritebmpx (write block multiplex primary) request.
7269 Always reply with an error, if someone has a platform really needs this,
7270 please contact vl@samba.org
7271 ****************************************************************************/
7273 void reply_writebmpx(struct smb_request *req)
7275 START_PROFILE(SMBwriteBmpx);
7276 reply_doserror(req, ERRSRV, ERRuseSTD);
7277 END_PROFILE(SMBwriteBmpx);
7281 /****************************************************************************
7282 Reply to a SMBwritebs (write block multiplex secondary) request.
7283 Always reply with an error, if someone has a platform really needs this,
7284 please contact vl@samba.org
7285 ****************************************************************************/
7287 void reply_writebs(struct smb_request *req)
7289 START_PROFILE(SMBwriteBs);
7290 reply_doserror(req, ERRSRV, ERRuseSTD);
7291 END_PROFILE(SMBwriteBs);
7295 /****************************************************************************
7296 Reply to a SMBgetattrE.
7297 ****************************************************************************/
7299 void reply_getattrE(struct smb_request *req)
7301 connection_struct *conn = req->conn;
7302 SMB_STRUCT_STAT sbuf;
7305 struct timespec create_ts;
7307 START_PROFILE(SMBgetattrE);
7310 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7311 END_PROFILE(SMBgetattrE);
7315 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7317 if(!fsp || (fsp->conn != conn)) {
7318 reply_doserror(req, ERRDOS, ERRbadfid);
7319 END_PROFILE(SMBgetattrE);
7323 /* Do an fstat on this file */
7324 if(fsp_stat(fsp, &sbuf)) {
7325 reply_unixerror(req, ERRDOS, ERRnoaccess);
7326 END_PROFILE(SMBgetattrE);
7330 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7333 * Convert the times into dos times. Set create
7334 * date to be last modify date as UNIX doesn't save
7338 reply_outbuf(req, 11, 0);
7340 create_ts = get_create_timespec(&sbuf,
7341 lp_fake_dir_create_times(SNUM(conn)));
7342 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7343 srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7344 /* Should we check pending modtime here ? JRA */
7345 srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7348 SIVAL(req->outbuf, smb_vwv6, 0);
7349 SIVAL(req->outbuf, smb_vwv8, 0);
7351 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7352 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7353 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7355 SSVAL(req->outbuf,smb_vwv10, mode);
7357 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7359 END_PROFILE(SMBgetattrE);