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);
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 timespec ts[2];
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 ts[1] = 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 if ((dirtype&0x1F) == aVOLID) {
1384 char buf[DIR_STRUCT_SIZE];
1385 memcpy(buf,status,21);
1386 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1387 0,aVOLID,0,!allow_long_path_components)) {
1388 reply_nterror(req, NT_STATUS_NO_MEMORY);
1389 END_PROFILE(SMBsearch);
1392 dptr_fill(buf+12,dptr_num);
1393 if (dptr_zero(buf+12) && (status_len==0)) {
1398 if (message_push_blob(&req->outbuf,
1399 data_blob_const(buf, sizeof(buf)))
1401 reply_nterror(req, NT_STATUS_NO_MEMORY);
1402 END_PROFILE(SMBsearch);
1410 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1413 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1414 conn->dirpath,lp_dontdescend(SNUM(conn))));
1415 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1416 check_descend = True;
1419 for (i=numentries;(i<maxentries) && !finished;i++) {
1420 finished = !get_dir_entry(ctx,
1431 char buf[DIR_STRUCT_SIZE];
1432 memcpy(buf,status,21);
1433 if (!make_dir_struct(ctx,
1440 !allow_long_path_components)) {
1441 reply_nterror(req, NT_STATUS_NO_MEMORY);
1442 END_PROFILE(SMBsearch);
1445 if (!dptr_fill(buf+12,dptr_num)) {
1448 if (message_push_blob(&req->outbuf,
1449 data_blob_const(buf, sizeof(buf)))
1451 reply_nterror(req, NT_STATUS_NO_MEMORY);
1452 END_PROFILE(SMBsearch);
1462 /* If we were called as SMBffirst with smb_search_id == NULL
1463 and no entries were found then return error and close dirptr
1466 if (numentries == 0) {
1467 dptr_close(&dptr_num);
1468 } else if(expect_close && status_len == 0) {
1469 /* Close the dptr - we know it's gone */
1470 dptr_close(&dptr_num);
1473 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1474 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1475 dptr_close(&dptr_num);
1478 if ((numentries == 0) && !mask_contains_wcard) {
1479 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1480 END_PROFILE(SMBsearch);
1484 SSVAL(req->outbuf,smb_vwv0,numentries);
1485 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1486 SCVAL(smb_buf(req->outbuf),0,5);
1487 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1489 /* The replies here are never long name. */
1490 SSVAL(req->outbuf, smb_flg2,
1491 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1492 if (!allow_long_path_components) {
1493 SSVAL(req->outbuf, smb_flg2,
1494 SVAL(req->outbuf, smb_flg2)
1495 & (~FLAGS2_LONG_PATH_COMPONENTS));
1498 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1499 SSVAL(req->outbuf, smb_flg2,
1500 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1503 directory = dptr_path(dptr_num);
1506 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1507 smb_fn_name(req->cmd),
1509 directory ? directory : "./",
1514 END_PROFILE(SMBsearch);
1518 /****************************************************************************
1519 Reply to a fclose (stop directory search).
1520 ****************************************************************************/
1522 void reply_fclose(struct smb_request *req)
1530 bool path_contains_wcard = False;
1531 TALLOC_CTX *ctx = talloc_tos();
1533 START_PROFILE(SMBfclose);
1535 if (lp_posix_pathnames()) {
1536 reply_unknown_new(req, req->cmd);
1537 END_PROFILE(SMBfclose);
1541 p = (const char *)req->buf + 1;
1542 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1543 &err, &path_contains_wcard);
1544 if (!NT_STATUS_IS_OK(err)) {
1545 reply_nterror(req, err);
1546 END_PROFILE(SMBfclose);
1550 status_len = SVAL(p,0);
1553 if (status_len == 0) {
1554 reply_doserror(req, ERRSRV, ERRsrverror);
1555 END_PROFILE(SMBfclose);
1559 memcpy(status,p,21);
1561 if(dptr_fetch(status+12,&dptr_num)) {
1562 /* Close the dptr - we know it's gone */
1563 dptr_close(&dptr_num);
1566 reply_outbuf(req, 1, 0);
1567 SSVAL(req->outbuf,smb_vwv0,0);
1569 DEBUG(3,("search close\n"));
1571 END_PROFILE(SMBfclose);
1575 /****************************************************************************
1577 ****************************************************************************/
1579 void reply_open(struct smb_request *req)
1581 connection_struct *conn = req->conn;
1587 SMB_STRUCT_STAT sbuf;
1594 uint32 create_disposition;
1595 uint32 create_options = 0;
1597 TALLOC_CTX *ctx = talloc_tos();
1599 START_PROFILE(SMBopen);
1602 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1603 END_PROFILE(SMBopen);
1607 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1608 deny_mode = SVAL(req->vwv+0, 0);
1609 dos_attr = SVAL(req->vwv+1, 0);
1611 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1612 STR_TERMINATE, &status);
1613 if (!NT_STATUS_IS_OK(status)) {
1614 reply_nterror(req, status);
1615 END_PROFILE(SMBopen);
1619 if (!map_open_params_to_ntcreate(
1620 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1621 &share_mode, &create_disposition, &create_options)) {
1622 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1623 END_PROFILE(SMBopen);
1627 status = SMB_VFS_CREATE_FILE(
1630 0, /* root_dir_fid */
1632 CFF_DOS_PATH, /* create_file_flags */
1633 access_mask, /* access_mask */
1634 share_mode, /* share_access */
1635 create_disposition, /* create_disposition*/
1636 create_options, /* create_options */
1637 dos_attr, /* file_attributes */
1638 oplock_request, /* oplock_request */
1639 0, /* allocation_size */
1646 if (!NT_STATUS_IS_OK(status)) {
1647 if (open_was_deferred(req->mid)) {
1648 /* We have re-scheduled this call. */
1649 END_PROFILE(SMBopen);
1652 reply_openerror(req, status);
1653 END_PROFILE(SMBopen);
1657 size = sbuf.st_size;
1658 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1659 mtime = sbuf.st_mtime;
1662 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1663 close_file(req, fsp, ERROR_CLOSE);
1664 reply_doserror(req, ERRDOS,ERRnoaccess);
1665 END_PROFILE(SMBopen);
1669 reply_outbuf(req, 7, 0);
1670 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1671 SSVAL(req->outbuf,smb_vwv1,fattr);
1672 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1673 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1675 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1677 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1678 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1680 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1681 SCVAL(req->outbuf,smb_flg,
1682 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1685 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1686 SCVAL(req->outbuf,smb_flg,
1687 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1689 END_PROFILE(SMBopen);
1693 /****************************************************************************
1694 Reply to an open and X.
1695 ****************************************************************************/
1697 void reply_open_and_X(struct smb_request *req)
1699 connection_struct *conn = req->conn;
1704 /* Breakout the oplock request bits so we can set the
1705 reply bits separately. */
1706 int ex_oplock_request;
1707 int core_oplock_request;
1710 int smb_sattr = SVAL(req->vwv+4, 0);
1711 uint32 smb_time = make_unix_date3(req->vwv+6);
1716 SMB_STRUCT_STAT sbuf;
1720 uint64_t allocation_size;
1721 ssize_t retval = -1;
1724 uint32 create_disposition;
1725 uint32 create_options = 0;
1726 TALLOC_CTX *ctx = talloc_tos();
1728 START_PROFILE(SMBopenX);
1730 if (req->wct < 15) {
1731 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1732 END_PROFILE(SMBopenX);
1736 open_flags = SVAL(req->vwv+2, 0);
1737 deny_mode = SVAL(req->vwv+3, 0);
1738 smb_attr = SVAL(req->vwv+5, 0);
1739 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1740 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1741 oplock_request = ex_oplock_request | core_oplock_request;
1742 smb_ofun = SVAL(req->vwv+8, 0);
1743 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1745 /* If it's an IPC, pass off the pipe handler. */
1747 if (lp_nt_pipe_support()) {
1748 reply_open_pipe_and_X(conn, req);
1750 reply_doserror(req, ERRSRV, ERRaccess);
1752 END_PROFILE(SMBopenX);
1756 /* XXXX we need to handle passed times, sattr and flags */
1757 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1758 STR_TERMINATE, &status);
1759 if (!NT_STATUS_IS_OK(status)) {
1760 reply_nterror(req, status);
1761 END_PROFILE(SMBopenX);
1765 if (!map_open_params_to_ntcreate(
1766 fname, deny_mode, smb_ofun, &access_mask,
1767 &share_mode, &create_disposition, &create_options)) {
1768 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1769 END_PROFILE(SMBopenX);
1773 status = SMB_VFS_CREATE_FILE(
1776 0, /* root_dir_fid */
1778 CFF_DOS_PATH, /* create_file_flags */
1779 access_mask, /* access_mask */
1780 share_mode, /* share_access */
1781 create_disposition, /* create_disposition*/
1782 create_options, /* create_options */
1783 smb_attr, /* file_attributes */
1784 oplock_request, /* oplock_request */
1785 0, /* allocation_size */
1789 &smb_action, /* pinfo */
1792 if (!NT_STATUS_IS_OK(status)) {
1793 END_PROFILE(SMBopenX);
1794 if (open_was_deferred(req->mid)) {
1795 /* We have re-scheduled this call. */
1798 reply_openerror(req, status);
1802 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1803 if the file is truncated or created. */
1804 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1805 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1806 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1807 close_file(req, fsp, ERROR_CLOSE);
1808 reply_nterror(req, NT_STATUS_DISK_FULL);
1809 END_PROFILE(SMBopenX);
1812 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1814 close_file(req, fsp, ERROR_CLOSE);
1815 reply_nterror(req, NT_STATUS_DISK_FULL);
1816 END_PROFILE(SMBopenX);
1819 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1822 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1823 mtime = sbuf.st_mtime;
1825 close_file(req, fsp, ERROR_CLOSE);
1826 reply_doserror(req, ERRDOS, ERRnoaccess);
1827 END_PROFILE(SMBopenX);
1831 /* If the caller set the extended oplock request bit
1832 and we granted one (by whatever means) - set the
1833 correct bit for extended oplock reply.
1836 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1837 smb_action |= EXTENDED_OPLOCK_GRANTED;
1840 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1841 smb_action |= EXTENDED_OPLOCK_GRANTED;
1844 /* If the caller set the core oplock request bit
1845 and we granted one (by whatever means) - set the
1846 correct bit for core oplock reply.
1849 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1850 reply_outbuf(req, 19, 0);
1852 reply_outbuf(req, 15, 0);
1855 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1856 SCVAL(req->outbuf, smb_flg,
1857 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1860 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1861 SCVAL(req->outbuf, smb_flg,
1862 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1865 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1866 SSVAL(req->outbuf,smb_vwv3,fattr);
1867 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1868 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1870 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1872 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1873 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1874 SSVAL(req->outbuf,smb_vwv11,smb_action);
1876 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1877 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1880 END_PROFILE(SMBopenX);
1885 /****************************************************************************
1886 Reply to a SMBulogoffX.
1887 ****************************************************************************/
1889 void reply_ulogoffX(struct smb_request *req)
1893 START_PROFILE(SMBulogoffX);
1895 vuser = get_valid_user_struct(req->vuid);
1898 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1902 /* in user level security we are supposed to close any files
1903 open by this user */
1904 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1905 file_close_user(req->vuid);
1908 invalidate_vuid(req->vuid);
1910 reply_outbuf(req, 2, 0);
1912 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1914 END_PROFILE(SMBulogoffX);
1918 /****************************************************************************
1919 Reply to a mknew or a create.
1920 ****************************************************************************/
1922 void reply_mknew(struct smb_request *req)
1924 connection_struct *conn = req->conn;
1927 struct timespec ts[2];
1929 int oplock_request = 0;
1930 SMB_STRUCT_STAT sbuf;
1932 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1933 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1934 uint32 create_disposition;
1935 uint32 create_options = 0;
1936 TALLOC_CTX *ctx = talloc_tos();
1938 START_PROFILE(SMBcreate);
1941 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1942 END_PROFILE(SMBcreate);
1946 fattr = SVAL(req->vwv+0, 0);
1947 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1949 ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
1952 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
1953 STR_TERMINATE, &status);
1954 if (!NT_STATUS_IS_OK(status)) {
1955 reply_nterror(req, status);
1956 END_PROFILE(SMBcreate);
1960 if (fattr & aVOLID) {
1961 DEBUG(0,("Attempt to create file (%s) with volid set - "
1962 "please report this\n", fname));
1965 if(req->cmd == SMBmknew) {
1966 /* We should fail if file exists. */
1967 create_disposition = FILE_CREATE;
1969 /* Create if file doesn't exist, truncate if it does. */
1970 create_disposition = FILE_OVERWRITE_IF;
1973 status = SMB_VFS_CREATE_FILE(
1976 0, /* root_dir_fid */
1978 CFF_DOS_PATH, /* create_file_flags */
1979 access_mask, /* access_mask */
1980 share_mode, /* share_access */
1981 create_disposition, /* create_disposition*/
1982 create_options, /* create_options */
1983 fattr, /* file_attributes */
1984 oplock_request, /* oplock_request */
1985 0, /* allocation_size */
1992 if (!NT_STATUS_IS_OK(status)) {
1993 END_PROFILE(SMBcreate);
1994 if (open_was_deferred(req->mid)) {
1995 /* We have re-scheduled this call. */
1998 reply_openerror(req, status);
2002 ts[0] = get_atimespec(&sbuf); /* atime. */
2003 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, ts, true);
2004 if (!NT_STATUS_IS_OK(status)) {
2005 END_PROFILE(SMBcreate);
2006 reply_openerror(req, status);
2010 reply_outbuf(req, 1, 0);
2011 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2013 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2014 SCVAL(req->outbuf,smb_flg,
2015 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2018 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2019 SCVAL(req->outbuf,smb_flg,
2020 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2023 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2024 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2025 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2027 END_PROFILE(SMBcreate);
2031 /****************************************************************************
2032 Reply to a create temporary file.
2033 ****************************************************************************/
2035 void reply_ctemp(struct smb_request *req)
2037 connection_struct *conn = req->conn;
2043 SMB_STRUCT_STAT sbuf;
2046 TALLOC_CTX *ctx = talloc_tos();
2048 START_PROFILE(SMBctemp);
2051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2052 END_PROFILE(SMBctemp);
2056 fattr = SVAL(req->vwv+0, 0);
2057 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2059 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2060 STR_TERMINATE, &status);
2061 if (!NT_STATUS_IS_OK(status)) {
2062 reply_nterror(req, status);
2063 END_PROFILE(SMBctemp);
2067 fname = talloc_asprintf(ctx,
2071 fname = talloc_strdup(ctx, "TMXXXXXX");
2075 reply_nterror(req, NT_STATUS_NO_MEMORY);
2076 END_PROFILE(SMBctemp);
2080 status = resolve_dfspath(ctx, conn,
2081 req->flags2 & FLAGS2_DFS_PATHNAMES,
2084 if (!NT_STATUS_IS_OK(status)) {
2085 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2086 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2087 ERRSRV, ERRbadpath);
2088 END_PROFILE(SMBctemp);
2091 reply_nterror(req, status);
2092 END_PROFILE(SMBctemp);
2096 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
2097 if (!NT_STATUS_IS_OK(status)) {
2098 reply_nterror(req, status);
2099 END_PROFILE(SMBctemp);
2103 status = check_name(conn, fname);
2104 if (!NT_STATUS_IS_OK(status)) {
2105 reply_nterror(req, status);
2106 END_PROFILE(SMBctemp);
2110 tmpfd = smb_mkstemp(fname);
2112 reply_unixerror(req, ERRDOS, ERRnoaccess);
2113 END_PROFILE(SMBctemp);
2117 SMB_VFS_STAT(conn,fname,&sbuf);
2119 /* We should fail if file does not exist. */
2120 status = SMB_VFS_CREATE_FILE(
2123 0, /* root_dir_fid */
2125 0, /* create_file_flags */
2126 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2127 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2128 FILE_OPEN, /* create_disposition*/
2129 0, /* create_options */
2130 fattr, /* file_attributes */
2131 oplock_request, /* oplock_request */
2132 0, /* allocation_size */
2139 /* close fd from smb_mkstemp() */
2142 if (!NT_STATUS_IS_OK(status)) {
2143 if (open_was_deferred(req->mid)) {
2144 /* We have re-scheduled this call. */
2145 END_PROFILE(SMBctemp);
2148 reply_openerror(req, status);
2149 END_PROFILE(SMBctemp);
2153 reply_outbuf(req, 1, 0);
2154 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2156 /* the returned filename is relative to the directory */
2157 s = strrchr_m(fsp->fsp_name, '/');
2165 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2166 thing in the byte section. JRA */
2167 SSVALS(p, 0, -1); /* what is this? not in spec */
2169 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2171 reply_nterror(req, NT_STATUS_NO_MEMORY);
2172 END_PROFILE(SMBctemp);
2176 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2177 SCVAL(req->outbuf, smb_flg,
2178 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2181 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2182 SCVAL(req->outbuf, smb_flg,
2183 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2186 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2187 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2188 fsp->fh->fd, (unsigned int)sbuf.st_mode ) );
2190 END_PROFILE(SMBctemp);
2194 /*******************************************************************
2195 Check if a user is allowed to rename a file.
2196 ********************************************************************/
2198 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2199 uint16 dirtype, SMB_STRUCT_STAT *pst)
2203 if (!CAN_WRITE(conn)) {
2204 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2207 fmode = dos_mode(conn, fsp->fsp_name, pst);
2208 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2209 return NT_STATUS_NO_SUCH_FILE;
2212 if (S_ISDIR(pst->st_mode)) {
2213 return NT_STATUS_OK;
2216 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2217 return NT_STATUS_OK;
2220 return NT_STATUS_ACCESS_DENIED;
2223 /*******************************************************************
2224 * unlink a file with all relevant access checks
2225 *******************************************************************/
2227 static NTSTATUS do_unlink(connection_struct *conn,
2228 struct smb_request *req,
2232 SMB_STRUCT_STAT sbuf;
2235 uint32 dirtype_orig = dirtype;
2238 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2240 if (!CAN_WRITE(conn)) {
2241 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2244 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2245 return map_nt_error_from_unix(errno);
2248 fattr = dos_mode(conn,fname,&sbuf);
2250 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2251 dirtype = aDIR|aARCH|aRONLY;
2254 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2256 return NT_STATUS_NO_SUCH_FILE;
2259 if (!dir_check_ftype(conn, fattr, dirtype)) {
2261 return NT_STATUS_FILE_IS_A_DIRECTORY;
2263 return NT_STATUS_NO_SUCH_FILE;
2266 if (dirtype_orig & 0x8000) {
2267 /* These will never be set for POSIX. */
2268 return NT_STATUS_NO_SUCH_FILE;
2272 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2273 return NT_STATUS_FILE_IS_A_DIRECTORY;
2276 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2277 return NT_STATUS_NO_SUCH_FILE;
2280 if (dirtype & 0xFF00) {
2281 /* These will never be set for POSIX. */
2282 return NT_STATUS_NO_SUCH_FILE;
2287 return NT_STATUS_NO_SUCH_FILE;
2290 /* Can't delete a directory. */
2292 return NT_STATUS_FILE_IS_A_DIRECTORY;
2297 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2298 return NT_STATUS_OBJECT_NAME_INVALID;
2299 #endif /* JRATEST */
2301 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2303 On a Windows share, a file with read-only dosmode can be opened with
2304 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2305 fails with NT_STATUS_CANNOT_DELETE error.
2307 This semantic causes a problem that a user can not
2308 rename a file with read-only dosmode on a Samba share
2309 from a Windows command prompt (i.e. cmd.exe, but can rename
2310 from Windows Explorer).
2313 if (!lp_delete_readonly(SNUM(conn))) {
2314 if (fattr & aRONLY) {
2315 return NT_STATUS_CANNOT_DELETE;
2319 /* On open checks the open itself will check the share mode, so
2320 don't do it here as we'll get it wrong. */
2322 status = SMB_VFS_CREATE_FILE
2325 0, /* root_dir_fid */
2327 0, /* create_file_flags */
2328 DELETE_ACCESS, /* access_mask */
2329 FILE_SHARE_NONE, /* share_access */
2330 FILE_OPEN, /* create_disposition*/
2331 FILE_NON_DIRECTORY_FILE, /* create_options */
2332 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2333 0, /* oplock_request */
2334 0, /* allocation_size */
2341 if (!NT_STATUS_IS_OK(status)) {
2342 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2343 nt_errstr(status)));
2347 /* The set is across all open files on this dev/inode pair. */
2348 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2349 close_file(req, fsp, NORMAL_CLOSE);
2350 return NT_STATUS_ACCESS_DENIED;
2353 return close_file(req, fsp, NORMAL_CLOSE);
2356 /****************************************************************************
2357 The guts of the unlink command, split out so it may be called by the NT SMB
2359 ****************************************************************************/
2361 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2362 uint32 dirtype, const char *name_in, bool has_wild)
2364 const char *directory = NULL;
2369 NTSTATUS status = NT_STATUS_OK;
2370 SMB_STRUCT_STAT sbuf;
2371 TALLOC_CTX *ctx = talloc_tos();
2373 status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
2374 if (!NT_STATUS_IS_OK(status)) {
2378 p = strrchr_m(name,'/');
2380 directory = talloc_strdup(ctx, ".");
2382 return NT_STATUS_NO_MEMORY;
2392 * We should only check the mangled cache
2393 * here if unix_convert failed. This means
2394 * that the path in 'mask' doesn't exist
2395 * on the file system and so we need to look
2396 * for a possible mangle. This patch from
2397 * Tine Smukavec <valentin.smukavec@hermes.si>.
2400 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
2401 char *new_mask = NULL;
2402 mangle_lookup_name_from_8_3(ctx,
2412 directory = talloc_asprintf(ctx,
2417 return NT_STATUS_NO_MEMORY;
2420 dirtype = FILE_ATTRIBUTE_NORMAL;
2423 status = check_name(conn, directory);
2424 if (!NT_STATUS_IS_OK(status)) {
2428 status = do_unlink(conn, req, directory, dirtype);
2429 if (!NT_STATUS_IS_OK(status)) {
2435 struct smb_Dir *dir_hnd = NULL;
2439 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2440 return NT_STATUS_OBJECT_NAME_INVALID;
2443 if (strequal(mask,"????????.???")) {
2448 status = check_name(conn, directory);
2449 if (!NT_STATUS_IS_OK(status)) {
2453 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2455 if (dir_hnd == NULL) {
2456 return map_nt_error_from_unix(errno);
2459 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2460 the pattern matches against the long name, otherwise the short name
2461 We don't implement this yet XXXX
2464 status = NT_STATUS_NO_SUCH_FILE;
2466 while ((dname = ReadDirName(dir_hnd, &offset))) {
2470 if (!is_visible_file(conn, directory, dname, &st, True)) {
2474 /* Quick check for "." and ".." */
2475 if (ISDOT(dname) || ISDOTDOT(dname)) {
2479 if(!mask_match(dname, mask, conn->case_sensitive)) {
2483 fname = talloc_asprintf(ctx, "%s/%s",
2487 return NT_STATUS_NO_MEMORY;
2490 status = check_name(conn, fname);
2491 if (!NT_STATUS_IS_OK(status)) {
2492 TALLOC_FREE(dir_hnd);
2496 status = do_unlink(conn, req, fname, dirtype);
2497 if (!NT_STATUS_IS_OK(status)) {
2503 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2508 TALLOC_FREE(dir_hnd);
2511 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2512 status = map_nt_error_from_unix(errno);
2518 /****************************************************************************
2520 ****************************************************************************/
2522 void reply_unlink(struct smb_request *req)
2524 connection_struct *conn = req->conn;
2528 bool path_contains_wcard = False;
2529 TALLOC_CTX *ctx = talloc_tos();
2531 START_PROFILE(SMBunlink);
2534 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2535 END_PROFILE(SMBunlink);
2539 dirtype = SVAL(req->vwv+0, 0);
2541 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2542 STR_TERMINATE, &status,
2543 &path_contains_wcard);
2544 if (!NT_STATUS_IS_OK(status)) {
2545 reply_nterror(req, status);
2546 END_PROFILE(SMBunlink);
2550 status = resolve_dfspath_wcard(ctx, conn,
2551 req->flags2 & FLAGS2_DFS_PATHNAMES,
2554 &path_contains_wcard);
2555 if (!NT_STATUS_IS_OK(status)) {
2556 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2557 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2558 ERRSRV, ERRbadpath);
2559 END_PROFILE(SMBunlink);
2562 reply_nterror(req, status);
2563 END_PROFILE(SMBunlink);
2567 DEBUG(3,("reply_unlink : %s\n",name));
2569 status = unlink_internals(conn, req, dirtype, name,
2570 path_contains_wcard);
2571 if (!NT_STATUS_IS_OK(status)) {
2572 if (open_was_deferred(req->mid)) {
2573 /* We have re-scheduled this call. */
2574 END_PROFILE(SMBunlink);
2577 reply_nterror(req, status);
2578 END_PROFILE(SMBunlink);
2582 reply_outbuf(req, 0, 0);
2583 END_PROFILE(SMBunlink);
2588 /****************************************************************************
2590 ****************************************************************************/
2592 static void fail_readraw(void)
2594 const char *errstr = talloc_asprintf(talloc_tos(),
2595 "FAIL ! reply_readbraw: socket write fail (%s)",
2600 exit_server_cleanly(errstr);
2603 /****************************************************************************
2604 Fake (read/write) sendfile. Returns -1 on read or write fail.
2605 ****************************************************************************/
2607 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2611 size_t tosend = nread;
2618 bufsize = MIN(nread, 65536);
2620 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2624 while (tosend > 0) {
2628 if (tosend > bufsize) {
2633 ret = read_file(fsp,buf,startpos,cur_read);
2639 /* If we had a short read, fill with zeros. */
2640 if (ret < cur_read) {
2641 memset(buf, '\0', cur_read - ret);
2644 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2649 startpos += cur_read;
2653 return (ssize_t)nread;
2656 /****************************************************************************
2657 Deal with the case of sendfile reading less bytes from the file than
2658 requested. Fill with zeros (all we can do).
2659 ****************************************************************************/
2661 static void sendfile_short_send(files_struct *fsp,
2666 if (nread < headersize) {
2667 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2668 "header for file %s (%s). Terminating\n",
2669 fsp->fsp_name, strerror(errno) ));
2670 exit_server_cleanly("sendfile_short_send failed");
2673 nread -= headersize;
2675 if (nread < smb_maxcnt) {
2676 char *buf = SMB_CALLOC_ARRAY(char, 1024);
2678 exit_server_cleanly("sendfile_short_send: "
2682 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2683 "with zeros !\n", fsp->fsp_name));
2685 while (nread < smb_maxcnt) {
2687 * We asked for the real file size and told sendfile
2688 * to not go beyond the end of the file. But it can
2689 * happen that in between our fstat call and the
2690 * sendfile call the file was truncated. This is very
2691 * bad because we have already announced the larger
2692 * number of bytes to the client.
2694 * The best we can do now is to send 0-bytes, just as
2695 * a read from a hole in a sparse file would do.
2697 * This should happen rarely enough that I don't care
2698 * about efficiency here :-)
2702 to_write = MIN(sizeof(buf), smb_maxcnt - nread);
2703 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2704 exit_server_cleanly("sendfile_short_send: "
2705 "write_data failed");
2713 /****************************************************************************
2714 Return a readbraw error (4 bytes of zero).
2715 ****************************************************************************/
2717 static void reply_readbraw_error(void)
2721 if (write_data(smbd_server_fd(),header,4) != 4) {
2726 /****************************************************************************
2727 Use sendfile in readbraw.
2728 ****************************************************************************/
2730 void send_file_readbraw(connection_struct *conn,
2736 char *outbuf = NULL;
2739 #if defined(WITH_SENDFILE)
2741 * We can only use sendfile on a non-chained packet
2742 * but we can use on a non-oplocked file. tridge proved this
2743 * on a train in Germany :-). JRA.
2744 * reply_readbraw has already checked the length.
2747 if ( (chain_size == 0) && (nread > 0) && (fsp->base_fsp == NULL) &&
2748 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2749 ssize_t sendfile_read = -1;
2751 DATA_BLOB header_blob;
2753 _smb_setlen(header,nread);
2754 header_blob = data_blob_const(header, 4);
2756 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2757 &header_blob, startpos, nread)) == -1) {
2758 /* Returning ENOSYS means no data at all was sent.
2759 * Do this as a normal read. */
2760 if (errno == ENOSYS) {
2761 goto normal_readbraw;
2765 * Special hack for broken Linux with no working sendfile. If we
2766 * return EINTR we sent the header but not the rest of the data.
2767 * Fake this up by doing read/write calls.
2769 if (errno == EINTR) {
2770 /* Ensure we don't do this again. */
2771 set_use_sendfile(SNUM(conn), False);
2772 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2774 if (fake_sendfile(fsp, startpos, nread) == -1) {
2775 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2776 fsp->fsp_name, strerror(errno) ));
2777 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2782 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2783 fsp->fsp_name, strerror(errno) ));
2784 exit_server_cleanly("send_file_readbraw sendfile failed");
2787 /* Deal with possible short send. */
2788 sendfile_short_send(fsp, sendfile_read, 4, nread);
2795 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2797 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2798 (unsigned)(nread+4)));
2799 reply_readbraw_error();
2804 ret = read_file(fsp,outbuf+4,startpos,nread);
2805 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2814 _smb_setlen(outbuf,ret);
2815 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2818 TALLOC_FREE(outbuf);
2821 /****************************************************************************
2822 Reply to a readbraw (core+ protocol).
2823 ****************************************************************************/
2825 void reply_readbraw(struct smb_request *req)
2827 connection_struct *conn = req->conn;
2828 ssize_t maxcount,mincount;
2835 START_PROFILE(SMBreadbraw);
2837 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
2838 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2839 "raw reads/writes are disallowed.");
2843 reply_readbraw_error();
2844 END_PROFILE(SMBreadbraw);
2849 * Special check if an oplock break has been issued
2850 * and the readraw request croses on the wire, we must
2851 * return a zero length response here.
2854 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2857 * We have to do a check_fsp by hand here, as
2858 * we must always return 4 zero bytes on error,
2862 if (!fsp || !conn || conn != fsp->conn ||
2863 req->vuid != fsp->vuid ||
2864 fsp->is_directory || fsp->fh->fd == -1) {
2866 * fsp could be NULL here so use the value from the packet. JRA.
2868 DEBUG(3,("reply_readbraw: fnum %d not valid "
2870 (int)SVAL(req->vwv+0, 0)));
2871 reply_readbraw_error();
2872 END_PROFILE(SMBreadbraw);
2876 /* Do a "by hand" version of CHECK_READ. */
2877 if (!(fsp->can_read ||
2878 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2879 (fsp->access_mask & FILE_EXECUTE)))) {
2880 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2881 (int)SVAL(req->vwv+0, 0)));
2882 reply_readbraw_error();
2883 END_PROFILE(SMBreadbraw);
2887 flush_write_cache(fsp, READRAW_FLUSH);
2889 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
2890 if(req->wct == 10) {
2892 * This is a large offset (64 bit) read.
2894 #ifdef LARGE_SMB_OFF_T
2896 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
2898 #else /* !LARGE_SMB_OFF_T */
2901 * Ensure we haven't been sent a >32 bit offset.
2904 if(IVAL(req->vwv+8, 0) != 0) {
2905 DEBUG(0,("reply_readbraw: large offset "
2906 "(%x << 32) used and we don't support "
2907 "64 bit offsets.\n",
2908 (unsigned int)IVAL(req->vwv+8, 0) ));
2909 reply_readbraw_error();
2910 END_PROFILE(SMBreadbraw);
2914 #endif /* LARGE_SMB_OFF_T */
2917 DEBUG(0,("reply_readbraw: negative 64 bit "
2918 "readraw offset (%.0f) !\n",
2919 (double)startpos ));
2920 reply_readbraw_error();
2921 END_PROFILE(SMBreadbraw);
2926 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
2927 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
2929 /* ensure we don't overrun the packet size */
2930 maxcount = MIN(65535,maxcount);
2932 if (is_locked(fsp,(uint32)req->smbpid,
2936 reply_readbraw_error();
2937 END_PROFILE(SMBreadbraw);
2941 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
2945 if (startpos >= size) {
2948 nread = MIN(maxcount,(size - startpos));
2951 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2952 if (nread < mincount)
2956 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2957 "min=%lu nread=%lu\n",
2958 fsp->fnum, (double)startpos,
2959 (unsigned long)maxcount,
2960 (unsigned long)mincount,
2961 (unsigned long)nread ) );
2963 send_file_readbraw(conn, fsp, startpos, nread, mincount);
2965 DEBUG(5,("reply_readbraw finished\n"));
2966 END_PROFILE(SMBreadbraw);
2970 #define DBGC_CLASS DBGC_LOCKING
2972 /****************************************************************************
2973 Reply to a lockread (core+ protocol).
2974 ****************************************************************************/
2976 void reply_lockread(struct smb_request *req)
2978 connection_struct *conn = req->conn;
2985 struct byte_range_lock *br_lck = NULL;
2988 START_PROFILE(SMBlockread);
2991 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2992 END_PROFILE(SMBlockread);
2996 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2998 if (!check_fsp(conn, req, fsp)) {
2999 END_PROFILE(SMBlockread);
3003 if (!CHECK_READ(fsp,req)) {
3004 reply_doserror(req, ERRDOS, ERRbadaccess);
3005 END_PROFILE(SMBlockread);
3009 release_level_2_oplocks_on_change(fsp);
3011 numtoread = SVAL(req->vwv+1, 0);
3012 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3014 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3016 reply_outbuf(req, 5, numtoread + 3);
3018 data = smb_buf(req->outbuf) + 3;
3021 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3022 * protocol request that predates the read/write lock concept.
3023 * Thus instead of asking for a read lock here we need to ask
3024 * for a write lock. JRA.
3025 * Note that the requested lock size is unaffected by max_recv.
3028 br_lck = do_lock(smbd_messaging_context(),
3031 (uint64_t)numtoread,
3035 False, /* Non-blocking lock. */
3038 TALLOC_FREE(br_lck);
3040 if (NT_STATUS_V(status)) {
3041 reply_nterror(req, status);
3042 END_PROFILE(SMBlockread);
3047 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3050 if (numtoread > max_recv) {
3051 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3052 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3053 (unsigned int)numtoread, (unsigned int)max_recv ));
3054 numtoread = MIN(numtoread,max_recv);
3056 nread = read_file(fsp,data,startpos,numtoread);
3059 reply_unixerror(req, ERRDOS, ERRnoaccess);
3060 END_PROFILE(SMBlockread);
3064 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3066 SSVAL(req->outbuf,smb_vwv0,nread);
3067 SSVAL(req->outbuf,smb_vwv5,nread+3);
3068 p = smb_buf(req->outbuf);
3069 SCVAL(p,0,0); /* pad byte. */
3072 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3073 fsp->fnum, (int)numtoread, (int)nread));
3075 END_PROFILE(SMBlockread);
3080 #define DBGC_CLASS DBGC_ALL
3082 /****************************************************************************
3084 ****************************************************************************/
3086 void reply_read(struct smb_request *req)
3088 connection_struct *conn = req->conn;
3096 START_PROFILE(SMBread);
3099 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3100 END_PROFILE(SMBread);
3104 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3106 if (!check_fsp(conn, req, fsp)) {
3107 END_PROFILE(SMBread);
3111 if (!CHECK_READ(fsp,req)) {
3112 reply_doserror(req, ERRDOS, ERRbadaccess);
3113 END_PROFILE(SMBread);
3117 numtoread = SVAL(req->vwv+1, 0);
3118 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3120 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3123 * The requested read size cannot be greater than max_recv. JRA.
3125 if (numtoread > max_recv) {
3126 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3127 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3128 (unsigned int)numtoread, (unsigned int)max_recv ));
3129 numtoread = MIN(numtoread,max_recv);
3132 reply_outbuf(req, 5, numtoread+3);
3134 data = smb_buf(req->outbuf) + 3;
3136 if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtoread,
3137 (uint64_t)startpos, READ_LOCK)) {
3138 reply_doserror(req, ERRDOS,ERRlock);
3139 END_PROFILE(SMBread);
3144 nread = read_file(fsp,data,startpos,numtoread);
3147 reply_unixerror(req, ERRDOS,ERRnoaccess);
3148 END_PROFILE(SMBread);
3152 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3154 SSVAL(req->outbuf,smb_vwv0,nread);
3155 SSVAL(req->outbuf,smb_vwv5,nread+3);
3156 SCVAL(smb_buf(req->outbuf),0,1);
3157 SSVAL(smb_buf(req->outbuf),1,nread);
3159 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3160 fsp->fnum, (int)numtoread, (int)nread ) );
3162 END_PROFILE(SMBread);
3166 /****************************************************************************
3168 ****************************************************************************/
3170 static int setup_readX_header(char *outbuf, size_t smb_maxcnt)
3175 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3176 data = smb_buf(outbuf);
3178 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3180 SCVAL(outbuf,smb_vwv0,0xFF);
3181 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3182 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3183 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
3184 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3185 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
3186 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3187 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3191 /****************************************************************************
3192 Reply to a read and X - possibly using sendfile.
3193 ****************************************************************************/
3195 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3196 files_struct *fsp, SMB_OFF_T startpos,
3199 SMB_STRUCT_STAT sbuf;
3202 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3203 reply_unixerror(req, ERRDOS, ERRnoaccess);
3207 if (startpos > sbuf.st_size) {
3209 } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
3210 smb_maxcnt = (sbuf.st_size - startpos);
3213 if (smb_maxcnt == 0) {
3217 #if defined(WITH_SENDFILE)
3219 * We can only use sendfile on a non-chained packet
3220 * but we can use on a non-oplocked file. tridge proved this
3221 * on a train in Germany :-). JRA.
3224 if ((chain_size == 0) && (CVAL(req->vwv+0, 0) == 0xFF) &&
3225 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3226 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
3227 uint8 headerbuf[smb_size + 12 * 2];
3231 * Set up the packet header before send. We
3232 * assume here the sendfile will work (get the
3233 * correct amount of data).
3236 header = data_blob_const(headerbuf, sizeof(headerbuf));
3238 construct_reply_common_req(req, (char *)headerbuf);
3239 setup_readX_header((char *)headerbuf, smb_maxcnt);
3241 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3242 /* Returning ENOSYS means no data at all was sent.
3243 Do this as a normal read. */
3244 if (errno == ENOSYS) {
3249 * Special hack for broken Linux with no working sendfile. If we
3250 * return EINTR we sent the header but not the rest of the data.
3251 * Fake this up by doing read/write calls.
3254 if (errno == EINTR) {
3255 /* Ensure we don't do this again. */
3256 set_use_sendfile(SNUM(conn), False);
3257 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3258 nread = fake_sendfile(fsp, startpos,
3261 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3262 fsp->fsp_name, strerror(errno) ));
3263 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3265 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3266 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3267 /* No outbuf here means successful sendfile. */
3268 TALLOC_FREE(req->outbuf);
3272 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3273 fsp->fsp_name, strerror(errno) ));
3274 exit_server_cleanly("send_file_readX sendfile failed");
3277 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3278 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3280 /* Deal with possible short send. */
3281 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3283 /* No outbuf here means successful sendfile. */
3284 TALLOC_FREE(req->outbuf);
3291 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3292 uint8 headerbuf[smb_size + 2*12];
3294 construct_reply_common_req(req, (char *)headerbuf);
3295 setup_readX_header((char *)headerbuf, smb_maxcnt);
3297 /* Send out the header. */
3298 if (write_data(smbd_server_fd(), (char *)headerbuf,
3299 sizeof(headerbuf)) != sizeof(headerbuf)) {
3300 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3301 fsp->fsp_name, strerror(errno) ));
3302 exit_server_cleanly("send_file_readX sendfile failed");
3304 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3306 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3307 fsp->fsp_name, strerror(errno) ));
3308 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3310 TALLOC_FREE(req->outbuf);
3314 reply_outbuf(req, 12, smb_maxcnt);
3316 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3318 reply_unixerror(req, ERRDOS, ERRnoaccess);
3322 setup_readX_header((char *)req->outbuf, nread);
3324 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3325 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3330 /****************************************************************************
3331 Reply to a read and X.
3332 ****************************************************************************/
3334 void reply_read_and_X(struct smb_request *req)
3336 connection_struct *conn = req->conn;
3340 bool big_readX = False;
3342 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3345 START_PROFILE(SMBreadX);
3347 if ((req->wct != 10) && (req->wct != 12)) {
3348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3352 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3353 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3354 smb_maxcnt = SVAL(req->vwv+5, 0);
3356 /* If it's an IPC, pass off the pipe handler. */
3358 reply_pipe_read_and_X(req);
3359 END_PROFILE(SMBreadX);
3363 if (!check_fsp(conn, req, fsp)) {
3364 END_PROFILE(SMBreadX);
3368 if (!CHECK_READ(fsp,req)) {
3369 reply_doserror(req, ERRDOS,ERRbadaccess);
3370 END_PROFILE(SMBreadX);
3374 if (global_client_caps & CAP_LARGE_READX) {
3375 size_t upper_size = SVAL(req->vwv+7, 0);
3376 smb_maxcnt |= (upper_size<<16);
3377 if (upper_size > 1) {
3378 /* Can't do this on a chained packet. */
3379 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3380 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3381 END_PROFILE(SMBreadX);
3384 /* We currently don't do this on signed or sealed data. */
3385 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
3386 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3387 END_PROFILE(SMBreadX);
3390 /* Is there room in the reply for this data ? */
3391 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3393 NT_STATUS_INVALID_PARAMETER);
3394 END_PROFILE(SMBreadX);
3401 if (req->wct == 12) {
3402 #ifdef LARGE_SMB_OFF_T
3404 * This is a large offset (64 bit) read.
3406 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3408 #else /* !LARGE_SMB_OFF_T */
3411 * Ensure we haven't been sent a >32 bit offset.
3414 if(IVAL(req->vwv+10, 0) != 0) {
3415 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3416 "used and we don't support 64 bit offsets.\n",
3417 (unsigned int)IVAL(req->vwv+10, 0) ));
3418 END_PROFILE(SMBreadX);
3419 reply_doserror(req, ERRDOS, ERRbadaccess);
3423 #endif /* LARGE_SMB_OFF_T */
3427 if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)smb_maxcnt,
3428 (uint64_t)startpos, READ_LOCK)) {
3429 END_PROFILE(SMBreadX);
3430 reply_doserror(req, ERRDOS, ERRlock);
3435 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3436 END_PROFILE(SMBreadX);
3440 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3442 END_PROFILE(SMBreadX);
3446 /****************************************************************************
3447 Error replies to writebraw must have smb_wct == 1. Fix this up.
3448 ****************************************************************************/
3450 void error_to_writebrawerr(struct smb_request *req)
3452 uint8 *old_outbuf = req->outbuf;
3454 reply_outbuf(req, 1, 0);
3456 memcpy(req->outbuf, old_outbuf, smb_size);
3457 TALLOC_FREE(old_outbuf);
3460 /****************************************************************************
3461 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3462 ****************************************************************************/
3464 void reply_writebraw(struct smb_request *req)
3466 connection_struct *conn = req->conn;
3469 ssize_t total_written=0;
3470 size_t numtowrite=0;
3478 START_PROFILE(SMBwritebraw);
3481 * If we ever reply with an error, it must have the SMB command
3482 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3485 SCVAL(req->inbuf,smb_com,SMBwritec);
3487 if (srv_is_signing_active()) {
3488 END_PROFILE(SMBwritebraw);
3489 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3490 "raw reads/writes are disallowed.");
3493 if (req->wct < 12) {
3494 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3495 error_to_writebrawerr(req);
3496 END_PROFILE(SMBwritebraw);
3500 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3501 if (!check_fsp(conn, req, fsp)) {
3502 error_to_writebrawerr(req);
3503 END_PROFILE(SMBwritebraw);
3507 if (!CHECK_WRITE(fsp)) {
3508 reply_doserror(req, ERRDOS, ERRbadaccess);
3509 error_to_writebrawerr(req);
3510 END_PROFILE(SMBwritebraw);
3514 tcount = IVAL(req->vwv+1, 0);
3515 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3516 write_through = BITSETW(req->vwv+7,0);
3518 /* We have to deal with slightly different formats depending
3519 on whether we are using the core+ or lanman1.0 protocol */
3521 if(Protocol <= PROTOCOL_COREPLUS) {
3522 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3523 data = smb_buf(req->inbuf);
3525 numtowrite = SVAL(req->vwv+10, 0);
3526 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3529 /* Ensure we don't write bytes past the end of this packet. */
3530 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3531 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3532 error_to_writebrawerr(req);
3533 END_PROFILE(SMBwritebraw);
3537 if (is_locked(fsp,(uint32)req->smbpid,(uint64_t)tcount,
3538 (uint64_t)startpos, WRITE_LOCK)) {
3539 reply_doserror(req, ERRDOS, ERRlock);
3540 error_to_writebrawerr(req);
3541 END_PROFILE(SMBwritebraw);
3546 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3549 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3550 "wrote=%d sync=%d\n",
3551 fsp->fnum, (double)startpos, (int)numtowrite,
3552 (int)nwritten, (int)write_through));
3554 if (nwritten < (ssize_t)numtowrite) {
3555 reply_unixerror(req, ERRHRD, ERRdiskfull);
3556 error_to_writebrawerr(req);
3557 END_PROFILE(SMBwritebraw);
3561 total_written = nwritten;
3563 /* Allocate a buffer of 64k + length. */
3564 buf = TALLOC_ARRAY(NULL, char, 65540);
3566 reply_doserror(req, ERRDOS, ERRnomem);
3567 error_to_writebrawerr(req);
3568 END_PROFILE(SMBwritebraw);
3572 /* Return a SMBwritebraw message to the redirector to tell
3573 * it to send more bytes */
3575 memcpy(buf, req->inbuf, smb_size);
3576 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3577 SCVAL(buf,smb_com,SMBwritebraw);
3578 SSVALS(buf,smb_vwv0,0xFFFF);
3580 if (!srv_send_smb(smbd_server_fd(),
3582 IS_CONN_ENCRYPTED(conn))) {
3583 exit_server_cleanly("reply_writebraw: srv_send_smb "
3587 /* Now read the raw data into the buffer and write it */
3588 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3590 if (!NT_STATUS_IS_OK(status)) {
3591 exit_server_cleanly("secondary writebraw failed");
3594 /* Set up outbuf to return the correct size */
3595 reply_outbuf(req, 1, 0);
3597 if (numtowrite != 0) {
3599 if (numtowrite > 0xFFFF) {
3600 DEBUG(0,("reply_writebraw: Oversize secondary write "
3601 "raw requested (%u). Terminating\n",
3602 (unsigned int)numtowrite ));
3603 exit_server_cleanly("secondary writebraw failed");
3606 if (tcount > nwritten+numtowrite) {
3607 DEBUG(3,("reply_writebraw: Client overestimated the "
3609 (int)tcount,(int)nwritten,(int)numtowrite));
3612 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3614 if (!NT_STATUS_IS_OK(status)) {
3615 DEBUG(0,("reply_writebraw: Oversize secondary write "
3616 "raw read failed (%s). Terminating\n",
3617 nt_errstr(status)));
3618 exit_server_cleanly("secondary writebraw failed");
3621 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3622 if (nwritten == -1) {
3624 reply_unixerror(req, ERRHRD, ERRdiskfull);
3625 error_to_writebrawerr(req);
3626 END_PROFILE(SMBwritebraw);
3630 if (nwritten < (ssize_t)numtowrite) {
3631 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3632 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3636 total_written += nwritten;
3641 SSVAL(req->outbuf,smb_vwv0,total_written);
3643 status = sync_file(conn, fsp, write_through);
3644 if (!NT_STATUS_IS_OK(status)) {
3645 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3646 fsp->fsp_name, nt_errstr(status) ));
3647 reply_nterror(req, status);
3648 error_to_writebrawerr(req);
3649 END_PROFILE(SMBwritebraw);
3653 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3655 fsp->fnum, (double)startpos, (int)numtowrite,
3656 (int)total_written));
3658 /* We won't return a status if write through is not selected - this
3659 * follows what WfWg does */
3660 END_PROFILE(SMBwritebraw);
3662 if (!write_through && total_written==tcount) {
3664 #if RABBIT_PELLET_FIX
3666 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3667 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3670 if (!send_keepalive(smbd_server_fd())) {
3671 exit_server_cleanly("reply_writebraw: send of "
3672 "keepalive failed");
3675 TALLOC_FREE(req->outbuf);
3681 #define DBGC_CLASS DBGC_LOCKING
3683 /****************************************************************************
3684 Reply to a writeunlock (core+).
3685 ****************************************************************************/
3687 void reply_writeunlock(struct smb_request *req)
3689 connection_struct *conn = req->conn;
3690 ssize_t nwritten = -1;
3694 NTSTATUS status = NT_STATUS_OK;
3697 START_PROFILE(SMBwriteunlock);
3700 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3701 END_PROFILE(SMBwriteunlock);
3705 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3707 if (!check_fsp(conn, req, fsp)) {
3708 END_PROFILE(SMBwriteunlock);
3712 if (!CHECK_WRITE(fsp)) {
3713 reply_doserror(req, ERRDOS,ERRbadaccess);
3714 END_PROFILE(SMBwriteunlock);
3718 numtowrite = SVAL(req->vwv+1, 0);
3719 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3720 data = (const char *)req->buf + 3;
3723 && is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
3724 (uint64_t)startpos, WRITE_LOCK)) {
3725 reply_doserror(req, ERRDOS, ERRlock);
3726 END_PROFILE(SMBwriteunlock);
3730 /* The special X/Open SMB protocol handling of
3731 zero length writes is *NOT* done for
3733 if(numtowrite == 0) {
3736 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3739 status = sync_file(conn, fsp, False /* write through */);
3740 if (!NT_STATUS_IS_OK(status)) {
3741 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3742 fsp->fsp_name, nt_errstr(status) ));
3743 reply_nterror(req, status);
3744 END_PROFILE(SMBwriteunlock);
3748 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3749 reply_unixerror(req, ERRHRD, ERRdiskfull);
3750 END_PROFILE(SMBwriteunlock);
3755 status = do_unlock(smbd_messaging_context(),
3758 (uint64_t)numtowrite,
3762 if (NT_STATUS_V(status)) {
3763 reply_nterror(req, status);
3764 END_PROFILE(SMBwriteunlock);
3769 reply_outbuf(req, 1, 0);
3771 SSVAL(req->outbuf,smb_vwv0,nwritten);
3773 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3774 fsp->fnum, (int)numtowrite, (int)nwritten));
3776 END_PROFILE(SMBwriteunlock);
3781 #define DBGC_CLASS DBGC_ALL
3783 /****************************************************************************
3785 ****************************************************************************/
3787 void reply_write(struct smb_request *req)
3789 connection_struct *conn = req->conn;
3791 ssize_t nwritten = -1;
3797 START_PROFILE(SMBwrite);
3800 END_PROFILE(SMBwrite);
3801 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3805 /* If it's an IPC, pass off the pipe handler. */
3807 reply_pipe_write(req);
3808 END_PROFILE(SMBwrite);
3812 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3814 if (!check_fsp(conn, req, fsp)) {
3815 END_PROFILE(SMBwrite);
3819 if (!CHECK_WRITE(fsp)) {
3820 reply_doserror(req, ERRDOS, ERRbadaccess);
3821 END_PROFILE(SMBwrite);
3825 numtowrite = SVAL(req->vwv+1, 0);
3826 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3827 data = (const char *)req->buf + 3;
3829 if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
3830 (uint64_t)startpos, WRITE_LOCK)) {
3831 reply_doserror(req, ERRDOS, ERRlock);
3832 END_PROFILE(SMBwrite);
3837 * X/Open SMB protocol says that if smb_vwv1 is
3838 * zero then the file size should be extended or
3839 * truncated to the size given in smb_vwv[2-3].
3842 if(numtowrite == 0) {
3844 * This is actually an allocate call, and set EOF. JRA.
3846 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3848 reply_nterror(req, NT_STATUS_DISK_FULL);
3849 END_PROFILE(SMBwrite);
3852 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3854 reply_nterror(req, NT_STATUS_DISK_FULL);
3855 END_PROFILE(SMBwrite);
3858 trigger_write_time_update_immediate(fsp);
3860 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3863 status = sync_file(conn, fsp, False);
3864 if (!NT_STATUS_IS_OK(status)) {
3865 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3866 fsp->fsp_name, nt_errstr(status) ));
3867 reply_nterror(req, status);
3868 END_PROFILE(SMBwrite);
3872 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3873 reply_unixerror(req, ERRHRD, ERRdiskfull);
3874 END_PROFILE(SMBwrite);
3878 reply_outbuf(req, 1, 0);
3880 SSVAL(req->outbuf,smb_vwv0,nwritten);
3882 if (nwritten < (ssize_t)numtowrite) {
3883 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3884 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3887 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3889 END_PROFILE(SMBwrite);
3893 /****************************************************************************
3894 Ensure a buffer is a valid writeX for recvfile purposes.
3895 ****************************************************************************/
3897 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3898 (2*14) + /* word count (including bcc) */ \
3901 bool is_valid_writeX_buffer(const uint8_t *inbuf)
3904 connection_struct *conn = NULL;
3905 unsigned int doff = 0;
3906 size_t len = smb_len_large(inbuf);
3908 if (is_encrypted_packet(inbuf)) {
3909 /* Can't do this on encrypted
3914 if (CVAL(inbuf,smb_com) != SMBwriteX) {
3918 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
3919 CVAL(inbuf,smb_wct) != 14) {
3920 DEBUG(10,("is_valid_writeX_buffer: chained or "
3921 "invalid word length.\n"));
3925 conn = conn_find(SVAL(inbuf, smb_tid));
3927 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
3931 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
3934 if (IS_PRINT(conn)) {
3935 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
3938 doff = SVAL(inbuf,smb_vwv11);
3940 numtowrite = SVAL(inbuf,smb_vwv10);
3942 if (len > doff && len - doff > 0xFFFF) {
3943 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
3946 if (numtowrite == 0) {
3947 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
3951 /* Ensure the sizes match up. */
3952 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
3953 /* no pad byte...old smbclient :-( */
3954 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
3956 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
3960 if (len - doff != numtowrite) {
3961 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
3962 "len = %u, doff = %u, numtowrite = %u\n",
3965 (unsigned int)numtowrite ));
3969 DEBUG(10,("is_valid_writeX_buffer: true "
3970 "len = %u, doff = %u, numtowrite = %u\n",
3973 (unsigned int)numtowrite ));
3978 /****************************************************************************
3979 Reply to a write and X.
3980 ****************************************************************************/
3982 void reply_write_and_X(struct smb_request *req)
3984 connection_struct *conn = req->conn;
3990 unsigned int smb_doff;
3991 unsigned int smblen;
3995 START_PROFILE(SMBwriteX);
3997 if ((req->wct != 12) && (req->wct != 14)) {
3998 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3999 END_PROFILE(SMBwriteX);
4003 numtowrite = SVAL(req->vwv+10, 0);
4004 smb_doff = SVAL(req->vwv+11, 0);
4005 smblen = smb_len(req->inbuf);
4007 if (req->unread_bytes > 0xFFFF ||
4008 (smblen > smb_doff &&
4009 smblen - smb_doff > 0xFFFF)) {
4010 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4013 if (req->unread_bytes) {
4014 /* Can't do a recvfile write on IPC$ */
4016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4017 END_PROFILE(SMBwriteX);
4020 if (numtowrite != req->unread_bytes) {
4021 reply_doserror(req, ERRDOS, ERRbadmem);
4022 END_PROFILE(SMBwriteX);
4026 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4027 smb_doff + numtowrite > smblen) {
4028 reply_doserror(req, ERRDOS, ERRbadmem);
4029 END_PROFILE(SMBwriteX);
4034 /* If it's an IPC, pass off the pipe handler. */
4036 if (req->unread_bytes) {
4037 reply_doserror(req, ERRDOS, ERRbadmem);
4038 END_PROFILE(SMBwriteX);
4041 reply_pipe_write_and_X(req);
4042 END_PROFILE(SMBwriteX);
4046 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4047 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4048 write_through = BITSETW(req->vwv+7,0);
4050 if (!check_fsp(conn, req, fsp)) {
4051 END_PROFILE(SMBwriteX);
4055 if (!CHECK_WRITE(fsp)) {
4056 reply_doserror(req, ERRDOS, ERRbadaccess);
4057 END_PROFILE(SMBwriteX);
4061 data = smb_base(req->inbuf) + smb_doff;
4063 if(req->wct == 14) {
4064 #ifdef LARGE_SMB_OFF_T
4066 * This is a large offset (64 bit) write.
4068 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4070 #else /* !LARGE_SMB_OFF_T */
4073 * Ensure we haven't been sent a >32 bit offset.
4076 if(IVAL(req->vwv+12, 0) != 0) {
4077 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4078 "used and we don't support 64 bit offsets.\n",
4079 (unsigned int)IVAL(req->vwv+12, 0) ));
4080 reply_doserror(req, ERRDOS, ERRbadaccess);
4081 END_PROFILE(SMBwriteX);
4085 #endif /* LARGE_SMB_OFF_T */
4088 if (is_locked(fsp,(uint32)req->smbpid,
4089 (uint64_t)numtowrite,
4090 (uint64_t)startpos, WRITE_LOCK)) {
4091 reply_doserror(req, ERRDOS, ERRlock);
4092 END_PROFILE(SMBwriteX);
4096 /* X/Open SMB protocol says that, unlike SMBwrite
4097 if the length is zero then NO truncation is
4098 done, just a write of zero. To truncate a file,
4101 if(numtowrite == 0) {
4105 if ((req->unread_bytes == 0) &&
4106 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4108 END_PROFILE(SMBwriteX);
4112 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4115 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4116 reply_unixerror(req, ERRHRD, ERRdiskfull);
4117 END_PROFILE(SMBwriteX);
4121 reply_outbuf(req, 6, 0);
4122 SSVAL(req->outbuf,smb_vwv2,nwritten);
4123 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4125 if (nwritten < (ssize_t)numtowrite) {
4126 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4127 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4130 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4131 fsp->fnum, (int)numtowrite, (int)nwritten));
4133 status = sync_file(conn, fsp, write_through);
4134 if (!NT_STATUS_IS_OK(status)) {
4135 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4136 fsp->fsp_name, nt_errstr(status) ));
4137 reply_nterror(req, status);
4138 END_PROFILE(SMBwriteX);
4142 END_PROFILE(SMBwriteX);
4147 /****************************************************************************
4149 ****************************************************************************/
4151 void reply_lseek(struct smb_request *req)
4153 connection_struct *conn = req->conn;
4159 START_PROFILE(SMBlseek);
4162 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4163 END_PROFILE(SMBlseek);
4167 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4169 if (!check_fsp(conn, req, fsp)) {
4173 flush_write_cache(fsp, SEEK_FLUSH);
4175 mode = SVAL(req->vwv+1, 0) & 3;
4176 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4177 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4186 res = fsp->fh->pos + startpos;
4197 if (umode == SEEK_END) {
4198 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4199 if(errno == EINVAL) {
4200 SMB_OFF_T current_pos = startpos;
4201 SMB_STRUCT_STAT sbuf;
4203 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4204 reply_unixerror(req, ERRDOS,
4206 END_PROFILE(SMBlseek);
4210 current_pos += sbuf.st_size;
4212 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4217 reply_unixerror(req, ERRDOS, ERRnoaccess);
4218 END_PROFILE(SMBlseek);
4225 reply_outbuf(req, 2, 0);
4226 SIVAL(req->outbuf,smb_vwv0,res);
4228 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4229 fsp->fnum, (double)startpos, (double)res, mode));
4231 END_PROFILE(SMBlseek);
4235 /****************************************************************************
4237 ****************************************************************************/
4239 void reply_flush(struct smb_request *req)
4241 connection_struct *conn = req->conn;
4245 START_PROFILE(SMBflush);
4248 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4252 fnum = SVAL(req->vwv+0, 0);
4253 fsp = file_fsp(req, fnum);
4255 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4260 file_sync_all(conn);
4262 NTSTATUS status = sync_file(conn, fsp, True);
4263 if (!NT_STATUS_IS_OK(status)) {
4264 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4265 fsp->fsp_name, nt_errstr(status) ));
4266 reply_nterror(req, status);
4267 END_PROFILE(SMBflush);
4272 reply_outbuf(req, 0, 0);
4274 DEBUG(3,("flush\n"));
4275 END_PROFILE(SMBflush);
4279 /****************************************************************************
4281 conn POINTER CAN BE NULL HERE !
4282 ****************************************************************************/
4284 void reply_exit(struct smb_request *req)
4286 START_PROFILE(SMBexit);
4288 file_close_pid(req->smbpid, req->vuid);
4290 reply_outbuf(req, 0, 0);
4292 DEBUG(3,("exit\n"));
4294 END_PROFILE(SMBexit);
4298 /****************************************************************************
4299 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4300 ****************************************************************************/
4302 void reply_close(struct smb_request *req)
4304 connection_struct *conn = req->conn;
4305 NTSTATUS status = NT_STATUS_OK;
4306 files_struct *fsp = NULL;
4307 START_PROFILE(SMBclose);
4310 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4311 END_PROFILE(SMBclose);
4315 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4318 * We can only use check_fsp if we know it's not a directory.
4321 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4322 reply_doserror(req, ERRDOS, ERRbadfid);
4323 END_PROFILE(SMBclose);
4327 if(fsp->is_directory) {
4329 * Special case - close NT SMB directory handle.
4331 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4332 status = close_file(req, fsp, NORMAL_CLOSE);
4336 * Close ordinary file.
4339 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4340 fsp->fh->fd, fsp->fnum,
4341 conn->num_files_open));
4344 * Take care of any time sent in the close.
4347 t = srv_make_unix_date3(req->vwv+1);
4348 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4351 * close_file() returns the unix errno if an error
4352 * was detected on close - normally this is due to
4353 * a disk full error. If not then it was probably an I/O error.
4356 status = close_file(req, fsp, NORMAL_CLOSE);
4359 if (!NT_STATUS_IS_OK(status)) {
4360 reply_nterror(req, status);
4361 END_PROFILE(SMBclose);
4365 reply_outbuf(req, 0, 0);
4366 END_PROFILE(SMBclose);
4370 /****************************************************************************
4371 Reply to a writeclose (Core+ protocol).
4372 ****************************************************************************/
4374 void reply_writeclose(struct smb_request *req)
4376 connection_struct *conn = req->conn;
4378 ssize_t nwritten = -1;
4379 NTSTATUS close_status = NT_STATUS_OK;
4382 struct timespec mtime;
4385 START_PROFILE(SMBwriteclose);
4388 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4389 END_PROFILE(SMBwriteclose);
4393 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4395 if (!check_fsp(conn, req, fsp)) {
4396 END_PROFILE(SMBwriteclose);
4399 if (!CHECK_WRITE(fsp)) {
4400 reply_doserror(req, ERRDOS,ERRbadaccess);
4401 END_PROFILE(SMBwriteclose);
4405 numtowrite = SVAL(req->vwv+1, 0);
4406 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4407 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4408 data = (const char *)req->buf + 1;
4411 && is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
4412 (uint64_t)startpos, WRITE_LOCK)) {
4413 reply_doserror(req, ERRDOS,ERRlock);
4414 END_PROFILE(SMBwriteclose);
4418 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4420 set_close_write_time(fsp, mtime);
4423 * More insanity. W2K only closes the file if writelen > 0.
4428 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4430 close_status = close_file(req, fsp, NORMAL_CLOSE);
4433 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4434 fsp->fnum, (int)numtowrite, (int)nwritten,
4435 conn->num_files_open));
4437 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4438 reply_doserror(req, ERRHRD, ERRdiskfull);
4439 END_PROFILE(SMBwriteclose);
4443 if(!NT_STATUS_IS_OK(close_status)) {
4444 reply_nterror(req, close_status);
4445 END_PROFILE(SMBwriteclose);
4449 reply_outbuf(req, 1, 0);
4451 SSVAL(req->outbuf,smb_vwv0,nwritten);
4452 END_PROFILE(SMBwriteclose);
4457 #define DBGC_CLASS DBGC_LOCKING
4459 /****************************************************************************
4461 ****************************************************************************/
4463 void reply_lock(struct smb_request *req)
4465 connection_struct *conn = req->conn;
4466 uint64_t count,offset;
4469 struct byte_range_lock *br_lck = NULL;
4471 START_PROFILE(SMBlock);
4474 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4475 END_PROFILE(SMBlock);
4479 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4481 if (!check_fsp(conn, req, fsp)) {
4482 END_PROFILE(SMBlock);
4486 release_level_2_oplocks_on_change(fsp);
4488 count = (uint64_t)IVAL(req->vwv+1, 0);
4489 offset = (uint64_t)IVAL(req->vwv+3, 0);
4491 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4492 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4494 br_lck = do_lock(smbd_messaging_context(),
4501 False, /* Non-blocking lock. */
4505 TALLOC_FREE(br_lck);
4507 if (NT_STATUS_V(status)) {
4508 reply_nterror(req, status);
4509 END_PROFILE(SMBlock);
4513 reply_outbuf(req, 0, 0);
4515 END_PROFILE(SMBlock);
4519 /****************************************************************************
4521 ****************************************************************************/
4523 void reply_unlock(struct smb_request *req)
4525 connection_struct *conn = req->conn;
4526 uint64_t count,offset;
4530 START_PROFILE(SMBunlock);
4533 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4534 END_PROFILE(SMBunlock);
4538 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4540 if (!check_fsp(conn, req, fsp)) {
4541 END_PROFILE(SMBunlock);
4545 count = (uint64_t)IVAL(req->vwv+1, 0);
4546 offset = (uint64_t)IVAL(req->vwv+3, 0);
4548 status = do_unlock(smbd_messaging_context(),
4555 if (NT_STATUS_V(status)) {
4556 reply_nterror(req, status);
4557 END_PROFILE(SMBunlock);
4561 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4562 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4564 reply_outbuf(req, 0, 0);
4566 END_PROFILE(SMBunlock);
4571 #define DBGC_CLASS DBGC_ALL
4573 /****************************************************************************
4575 conn POINTER CAN BE NULL HERE !
4576 ****************************************************************************/
4578 void reply_tdis(struct smb_request *req)
4580 connection_struct *conn = req->conn;
4581 START_PROFILE(SMBtdis);
4584 DEBUG(4,("Invalid connection in tdis\n"));
4585 reply_doserror(req, ERRSRV, ERRinvnid);
4586 END_PROFILE(SMBtdis);
4592 close_cnum(conn,req->vuid);
4595 reply_outbuf(req, 0, 0);
4596 END_PROFILE(SMBtdis);
4600 /****************************************************************************
4602 conn POINTER CAN BE NULL HERE !
4603 ****************************************************************************/
4605 void reply_echo(struct smb_request *req)
4607 connection_struct *conn = req->conn;
4611 START_PROFILE(SMBecho);
4614 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4615 END_PROFILE(SMBecho);
4619 smb_reverb = SVAL(req->vwv+0, 0);
4621 reply_outbuf(req, 1, req->buflen);
4623 /* copy any incoming data back out */
4624 if (req->buflen > 0) {
4625 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4628 if (smb_reverb > 100) {
4629 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4633 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
4634 SSVAL(req->outbuf,smb_vwv0,seq_num);
4636 show_msg((char *)req->outbuf);
4637 if (!srv_send_smb(smbd_server_fd(),
4638 (char *)req->outbuf,
4639 IS_CONN_ENCRYPTED(conn)||req->encrypted))
4640 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4643 DEBUG(3,("echo %d times\n", smb_reverb));
4645 TALLOC_FREE(req->outbuf);
4647 END_PROFILE(SMBecho);
4651 /****************************************************************************
4652 Reply to a printopen.
4653 ****************************************************************************/
4655 void reply_printopen(struct smb_request *req)
4657 connection_struct *conn = req->conn;
4659 SMB_STRUCT_STAT sbuf;
4662 START_PROFILE(SMBsplopen);
4665 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4666 END_PROFILE(SMBsplopen);
4670 if (!CAN_PRINT(conn)) {
4671 reply_doserror(req, ERRDOS, ERRnoaccess);
4672 END_PROFILE(SMBsplopen);
4676 status = file_new(req, conn, &fsp);
4677 if(!NT_STATUS_IS_OK(status)) {
4678 reply_nterror(req, status);
4679 END_PROFILE(SMBsplopen);
4683 /* Open for exclusive use, write only. */
4684 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4686 if (!NT_STATUS_IS_OK(status)) {
4687 reply_nterror(req, status);
4688 END_PROFILE(SMBsplopen);
4692 reply_outbuf(req, 1, 0);
4693 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4695 DEBUG(3,("openprint fd=%d fnum=%d\n",
4696 fsp->fh->fd, fsp->fnum));
4698 END_PROFILE(SMBsplopen);
4702 /****************************************************************************
4703 Reply to a printclose.
4704 ****************************************************************************/
4706 void reply_printclose(struct smb_request *req)
4708 connection_struct *conn = req->conn;
4712 START_PROFILE(SMBsplclose);
4715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4716 END_PROFILE(SMBsplclose);
4720 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4722 if (!check_fsp(conn, req, fsp)) {
4723 END_PROFILE(SMBsplclose);
4727 if (!CAN_PRINT(conn)) {
4728 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4729 END_PROFILE(SMBsplclose);
4733 DEBUG(3,("printclose fd=%d fnum=%d\n",
4734 fsp->fh->fd,fsp->fnum));
4736 status = close_file(req, fsp, NORMAL_CLOSE);
4738 if(!NT_STATUS_IS_OK(status)) {
4739 reply_nterror(req, status);
4740 END_PROFILE(SMBsplclose);
4744 reply_outbuf(req, 0, 0);
4746 END_PROFILE(SMBsplclose);
4750 /****************************************************************************
4751 Reply to a printqueue.
4752 ****************************************************************************/
4754 void reply_printqueue(struct smb_request *req)
4756 connection_struct *conn = req->conn;
4760 START_PROFILE(SMBsplretq);
4763 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4764 END_PROFILE(SMBsplretq);
4768 max_count = SVAL(req->vwv+0, 0);
4769 start_index = SVAL(req->vwv+1, 0);
4771 /* we used to allow the client to get the cnum wrong, but that
4772 is really quite gross and only worked when there was only
4773 one printer - I think we should now only accept it if they
4774 get it right (tridge) */
4775 if (!CAN_PRINT(conn)) {
4776 reply_doserror(req, ERRDOS, ERRnoaccess);
4777 END_PROFILE(SMBsplretq);
4781 reply_outbuf(req, 2, 3);
4782 SSVAL(req->outbuf,smb_vwv0,0);
4783 SSVAL(req->outbuf,smb_vwv1,0);
4784 SCVAL(smb_buf(req->outbuf),0,1);
4785 SSVAL(smb_buf(req->outbuf),1,0);
4787 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4788 start_index, max_count));
4791 print_queue_struct *queue = NULL;
4792 print_status_struct status;
4793 int count = print_queue_status(SNUM(conn), &queue, &status);
4794 int num_to_get = ABS(max_count);
4795 int first = (max_count>0?start_index:start_index+max_count+1);
4801 num_to_get = MIN(num_to_get,count-first);
4804 for (i=first;i<first+num_to_get;i++) {
4808 srv_put_dos_date2(p,0,queue[i].time);
4809 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4810 SSVAL(p,5, queue[i].job);
4811 SIVAL(p,7,queue[i].size);
4813 srvstr_push(blob, req->flags2, p+12,
4814 queue[i].fs_user, 16, STR_ASCII);
4816 if (message_push_blob(
4819 blob, sizeof(blob))) == -1) {
4820 reply_nterror(req, NT_STATUS_NO_MEMORY);
4821 END_PROFILE(SMBsplretq);
4827 SSVAL(req->outbuf,smb_vwv0,count);
4828 SSVAL(req->outbuf,smb_vwv1,
4829 (max_count>0?first+count:first-1));
4830 SCVAL(smb_buf(req->outbuf),0,1);
4831 SSVAL(smb_buf(req->outbuf),1,28*count);
4836 DEBUG(3,("%d entries returned in queue\n",count));
4839 END_PROFILE(SMBsplretq);
4843 /****************************************************************************
4844 Reply to a printwrite.
4845 ****************************************************************************/
4847 void reply_printwrite(struct smb_request *req)
4849 connection_struct *conn = req->conn;
4854 START_PROFILE(SMBsplwr);
4857 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4858 END_PROFILE(SMBsplwr);
4862 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4864 if (!check_fsp(conn, req, fsp)) {
4865 END_PROFILE(SMBsplwr);
4869 if (!CAN_PRINT(conn)) {
4870 reply_doserror(req, ERRDOS, ERRnoaccess);
4871 END_PROFILE(SMBsplwr);
4875 if (!CHECK_WRITE(fsp)) {
4876 reply_doserror(req, ERRDOS, ERRbadaccess);
4877 END_PROFILE(SMBsplwr);
4881 numtowrite = SVAL(req->buf, 1);
4883 if (req->buflen < numtowrite + 3) {
4884 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4885 END_PROFILE(SMBsplwr);
4889 data = (const char *)req->buf + 3;
4891 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
4892 reply_unixerror(req, ERRHRD, ERRdiskfull);
4893 END_PROFILE(SMBsplwr);
4897 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4899 END_PROFILE(SMBsplwr);
4903 /****************************************************************************
4905 ****************************************************************************/
4907 void reply_mkdir(struct smb_request *req)
4909 connection_struct *conn = req->conn;
4910 char *directory = NULL;
4912 SMB_STRUCT_STAT sbuf;
4913 TALLOC_CTX *ctx = talloc_tos();
4915 START_PROFILE(SMBmkdir);
4917 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
4918 STR_TERMINATE, &status);
4919 if (!NT_STATUS_IS_OK(status)) {
4920 reply_nterror(req, status);
4921 END_PROFILE(SMBmkdir);
4925 status = resolve_dfspath(ctx, conn,
4926 req->flags2 & FLAGS2_DFS_PATHNAMES,
4929 if (!NT_STATUS_IS_OK(status)) {
4930 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4931 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4932 ERRSRV, ERRbadpath);
4933 END_PROFILE(SMBmkdir);
4936 reply_nterror(req, status);
4937 END_PROFILE(SMBmkdir);
4941 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
4942 if (!NT_STATUS_IS_OK(status)) {
4943 reply_nterror(req, status);
4944 END_PROFILE(SMBmkdir);
4948 status = check_name(conn, directory);
4949 if (!NT_STATUS_IS_OK(status)) {
4950 reply_nterror(req, status);
4951 END_PROFILE(SMBmkdir);
4955 status = create_directory(conn, req, directory);
4957 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4959 if (!NT_STATUS_IS_OK(status)) {
4961 if (!use_nt_status()
4962 && NT_STATUS_EQUAL(status,
4963 NT_STATUS_OBJECT_NAME_COLLISION)) {
4965 * Yes, in the DOS error code case we get a
4966 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4967 * samba4 torture test.
4969 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4972 reply_nterror(req, status);
4973 END_PROFILE(SMBmkdir);
4977 reply_outbuf(req, 0, 0);
4979 DEBUG( 3, ( "mkdir %s\n", directory ) );
4981 END_PROFILE(SMBmkdir);
4985 /****************************************************************************
4986 Static function used by reply_rmdir to delete an entire directory
4987 tree recursively. Return True on ok, False on fail.
4988 ****************************************************************************/
4990 static bool recursive_rmdir(TALLOC_CTX *ctx,
4991 connection_struct *conn,
4994 const char *dname = NULL;
4997 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5003 while((dname = ReadDirName(dir_hnd, &offset))) {
5004 char *fullname = NULL;
5007 if (ISDOT(dname) || ISDOTDOT(dname)) {
5011 if (!is_visible_file(conn, directory, dname, &st, False)) {
5015 /* Construct the full name. */
5016 fullname = talloc_asprintf(ctx,
5026 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5031 if(st.st_mode & S_IFDIR) {
5032 if(!recursive_rmdir(ctx, conn, fullname)) {
5036 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5040 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5044 TALLOC_FREE(fullname);
5046 TALLOC_FREE(dir_hnd);
5050 /****************************************************************************
5051 The internals of the rmdir code - called elsewhere.
5052 ****************************************************************************/
5054 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5055 connection_struct *conn,
5056 const char *directory)
5061 /* Might be a symlink. */
5062 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5063 return map_nt_error_from_unix(errno);
5066 if (S_ISLNK(st.st_mode)) {
5067 /* Is what it points to a directory ? */
5068 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5069 return map_nt_error_from_unix(errno);
5071 if (!(S_ISDIR(st.st_mode))) {
5072 return NT_STATUS_NOT_A_DIRECTORY;
5074 ret = SMB_VFS_UNLINK(conn,directory);
5076 ret = SMB_VFS_RMDIR(conn,directory);
5079 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5080 FILE_NOTIFY_CHANGE_DIR_NAME,
5082 return NT_STATUS_OK;
5085 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5087 * Check to see if the only thing in this directory are
5088 * vetoed files/directories. If so then delete them and
5089 * retry. If we fail to delete any of them (and we *don't*
5090 * do a recursive delete) then fail the rmdir.
5094 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5095 directory, NULL, 0);
5097 if(dir_hnd == NULL) {
5102 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
5103 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5105 if (!is_visible_file(conn, directory, dname, &st, False))
5107 if(!IS_VETO_PATH(conn, dname)) {
5108 TALLOC_FREE(dir_hnd);
5114 /* We only have veto files/directories.
5115 * Are we allowed to delete them ? */
5117 if(!lp_recursive_veto_delete(SNUM(conn))) {
5118 TALLOC_FREE(dir_hnd);
5123 /* Do a recursive delete. */
5124 RewindDir(dir_hnd,&dirpos);
5125 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
5126 char *fullname = NULL;
5128 if (ISDOT(dname) || ISDOTDOT(dname)) {
5131 if (!is_visible_file(conn, directory, dname, &st, False)) {
5135 fullname = talloc_asprintf(ctx,
5145 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5148 if(st.st_mode & S_IFDIR) {
5149 if(!recursive_rmdir(ctx, conn, fullname)) {
5152 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5155 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5158 TALLOC_FREE(fullname);
5160 TALLOC_FREE(dir_hnd);
5161 /* Retry the rmdir */
5162 ret = SMB_VFS_RMDIR(conn,directory);
5168 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5169 "%s\n", directory,strerror(errno)));
5170 return map_nt_error_from_unix(errno);
5173 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5174 FILE_NOTIFY_CHANGE_DIR_NAME,
5177 return NT_STATUS_OK;
5180 /****************************************************************************
5182 ****************************************************************************/
5184 void reply_rmdir(struct smb_request *req)
5186 connection_struct *conn = req->conn;
5187 char *directory = NULL;
5188 SMB_STRUCT_STAT sbuf;
5190 TALLOC_CTX *ctx = talloc_tos();
5192 START_PROFILE(SMBrmdir);
5194 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5195 STR_TERMINATE, &status);
5196 if (!NT_STATUS_IS_OK(status)) {
5197 reply_nterror(req, status);
5198 END_PROFILE(SMBrmdir);
5202 status = resolve_dfspath(ctx, conn,
5203 req->flags2 & FLAGS2_DFS_PATHNAMES,
5206 if (!NT_STATUS_IS_OK(status)) {
5207 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5208 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5209 ERRSRV, ERRbadpath);
5210 END_PROFILE(SMBrmdir);
5213 reply_nterror(req, status);
5214 END_PROFILE(SMBrmdir);
5218 status = unix_convert(ctx, conn, directory, False, &directory,
5220 if (!NT_STATUS_IS_OK(status)) {
5221 reply_nterror(req, status);
5222 END_PROFILE(SMBrmdir);
5226 status = check_name(conn, directory);
5227 if (!NT_STATUS_IS_OK(status)) {
5228 reply_nterror(req, status);
5229 END_PROFILE(SMBrmdir);
5233 dptr_closepath(directory, req->smbpid);
5234 status = rmdir_internals(ctx, conn, directory);
5235 if (!NT_STATUS_IS_OK(status)) {
5236 reply_nterror(req, status);
5237 END_PROFILE(SMBrmdir);
5241 reply_outbuf(req, 0, 0);
5243 DEBUG( 3, ( "rmdir %s\n", directory ) );
5245 END_PROFILE(SMBrmdir);
5249 /*******************************************************************
5250 Resolve wildcards in a filename rename.
5251 ********************************************************************/
5253 static bool resolve_wildcards(TALLOC_CTX *ctx,
5258 char *name2_copy = NULL;
5263 char *p,*p2, *pname1, *pname2;
5265 name2_copy = talloc_strdup(ctx, name2);
5270 pname1 = strrchr_m(name1,'/');
5271 pname2 = strrchr_m(name2_copy,'/');
5273 if (!pname1 || !pname2) {
5277 /* Truncate the copy of name2 at the last '/' */
5280 /* Now go past the '/' */
5284 root1 = talloc_strdup(ctx, pname1);
5285 root2 = talloc_strdup(ctx, pname2);
5287 if (!root1 || !root2) {
5291 p = strrchr_m(root1,'.');
5294 ext1 = talloc_strdup(ctx, p+1);
5296 ext1 = talloc_strdup(ctx, "");
5298 p = strrchr_m(root2,'.');
5301 ext2 = talloc_strdup(ctx, p+1);
5303 ext2 = talloc_strdup(ctx, "");
5306 if (!ext1 || !ext2) {
5314 /* Hmmm. Should this be mb-aware ? */
5317 } else if (*p2 == '*') {
5319 root2 = talloc_asprintf(ctx, "%s%s",
5338 /* Hmmm. Should this be mb-aware ? */
5341 } else if (*p2 == '*') {
5343 ext2 = talloc_asprintf(ctx, "%s%s",
5359 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5364 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5376 /****************************************************************************
5377 Ensure open files have their names updated. Updated to notify other smbd's
5379 ****************************************************************************/
5381 static void rename_open_files(connection_struct *conn,
5382 struct share_mode_lock *lck,
5383 const char *newname)
5386 bool did_rename = False;
5388 for(fsp = file_find_di_first(lck->id); fsp;
5389 fsp = file_find_di_next(fsp)) {
5390 /* fsp_name is a relative path under the fsp. To change this for other
5391 sharepaths we need to manipulate relative paths. */
5392 /* TODO - create the absolute path and manipulate the newname
5393 relative to the sharepath. */
5394 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5397 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5398 fsp->fnum, file_id_string_tos(&fsp->file_id),
5399 fsp->fsp_name, newname ));
5400 string_set(&fsp->fsp_name, newname);
5405 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5406 file_id_string_tos(&lck->id), newname ));
5409 /* Send messages to all smbd's (not ourself) that the name has changed. */
5410 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5414 /****************************************************************************
5415 We need to check if the source path is a parent directory of the destination
5416 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5417 refuse the rename with a sharing violation. Under UNIX the above call can
5418 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5419 probably need to check that the client is a Windows one before disallowing
5420 this as a UNIX client (one with UNIX extensions) can know the source is a
5421 symlink and make this decision intelligently. Found by an excellent bug
5422 report from <AndyLiebman@aol.com>.
5423 ****************************************************************************/
5425 static bool rename_path_prefix_equal(const char *src, const char *dest)
5427 const char *psrc = src;
5428 const char *pdst = dest;
5431 if (psrc[0] == '.' && psrc[1] == '/') {
5434 if (pdst[0] == '.' && pdst[1] == '/') {
5437 if ((slen = strlen(psrc)) > strlen(pdst)) {
5440 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5444 * Do the notify calls from a rename
5447 static void notify_rename(connection_struct *conn, bool is_dir,
5448 const char *oldpath, const char *newpath)
5450 char *olddir, *newdir;
5451 const char *oldname, *newname;
5454 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5455 : FILE_NOTIFY_CHANGE_FILE_NAME;
5457 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5458 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5459 TALLOC_FREE(olddir);
5463 if (strcmp(olddir, newdir) == 0) {
5464 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5465 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5468 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5469 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5471 TALLOC_FREE(olddir);
5472 TALLOC_FREE(newdir);
5474 /* this is a strange one. w2k3 gives an additional event for
5475 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5476 files, but not directories */
5478 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5479 FILE_NOTIFY_CHANGE_ATTRIBUTES
5480 |FILE_NOTIFY_CHANGE_CREATION,
5485 /****************************************************************************
5486 Rename an open file - given an fsp.
5487 ****************************************************************************/
5489 NTSTATUS rename_internals_fsp(connection_struct *conn,
5492 const char *newname_last_component,
5494 bool replace_if_exists)
5496 TALLOC_CTX *ctx = talloc_tos();
5497 SMB_STRUCT_STAT sbuf, sbuf1;
5498 NTSTATUS status = NT_STATUS_OK;
5499 struct share_mode_lock *lck = NULL;
5500 bool dst_exists, old_is_stream, new_is_stream;
5504 status = check_name(conn, newname);
5505 if (!NT_STATUS_IS_OK(status)) {
5509 /* Ensure newname contains a '/' */
5510 if(strrchr_m(newname,'/') == 0) {
5511 newname = talloc_asprintf(ctx,
5515 return NT_STATUS_NO_MEMORY;
5520 * Check for special case with case preserving and not
5521 * case sensitive. If the old last component differs from the original
5522 * last component only by case, then we should allow
5523 * the rename (user is trying to change the case of the
5527 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5528 strequal(newname, fsp->fsp_name)) {
5530 char *newname_modified_last_component = NULL;
5533 * Get the last component of the modified name.
5534 * Note that we guarantee that newname contains a '/'
5537 p = strrchr_m(newname,'/');
5538 newname_modified_last_component = talloc_strdup(ctx,
5540 if (!newname_modified_last_component) {
5541 return NT_STATUS_NO_MEMORY;
5544 if(strcsequal(newname_modified_last_component,
5545 newname_last_component) == False) {
5547 * Replace the modified last component with
5550 *p = '\0'; /* Truncate at the '/' */
5551 newname = talloc_asprintf(ctx,
5554 newname_last_component);
5559 * If the src and dest names are identical - including case,
5560 * don't do the rename, just return success.
5563 if (strcsequal(fsp->fsp_name, newname)) {
5564 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5566 return NT_STATUS_OK;
5569 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5570 new_is_stream = is_ntfs_stream_name(newname);
5572 /* Return the correct error code if both names aren't streams. */
5573 if (!old_is_stream && new_is_stream) {
5574 return NT_STATUS_OBJECT_NAME_INVALID;
5577 if (old_is_stream && !new_is_stream) {
5578 return NT_STATUS_INVALID_PARAMETER;
5582 * Have vfs_object_exist also fill sbuf1
5584 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5586 if(!replace_if_exists && dst_exists) {
5587 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5588 fsp->fsp_name,newname));
5589 return NT_STATUS_OBJECT_NAME_COLLISION;
5593 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5594 files_struct *dst_fsp = file_find_di_first(fileid);
5595 /* The file can be open when renaming a stream */
5596 if (dst_fsp && !new_is_stream) {
5597 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5598 return NT_STATUS_ACCESS_DENIED;
5602 /* Ensure we have a valid stat struct for the source. */
5603 if (fsp->fh->fd != -1) {
5604 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5605 return map_nt_error_from_unix(errno);
5608 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
5609 return map_nt_error_from_unix(errno);
5613 status = can_rename(conn, fsp, attrs, &sbuf);
5615 if (!NT_STATUS_IS_OK(status)) {
5616 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5617 nt_errstr(status), fsp->fsp_name,newname));
5618 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5619 status = NT_STATUS_ACCESS_DENIED;
5623 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5624 return NT_STATUS_ACCESS_DENIED;
5627 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5631 * We have the file open ourselves, so not being able to get the
5632 * corresponding share mode lock is a fatal error.
5635 SMB_ASSERT(lck != NULL);
5637 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5638 uint32 create_options = fsp->fh->private_options;
5640 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5641 fsp->fsp_name,newname));
5643 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5645 rename_open_files(conn, lck, newname);
5648 * A rename acts as a new file create w.r.t. allowing an initial delete
5649 * on close, probably because in Windows there is a new handle to the
5650 * new file. If initial delete on close was requested but not
5651 * originally set, we need to set it here. This is probably not 100% correct,
5652 * but will work for the CIFSFS client which in non-posix mode
5653 * depends on these semantics. JRA.
5656 if (create_options & FILE_DELETE_ON_CLOSE) {
5657 status = can_set_delete_on_close(fsp, True, 0);
5659 if (NT_STATUS_IS_OK(status)) {
5660 /* Note that here we set the *inital* delete on close flag,
5661 * not the regular one. The magic gets handled in close. */
5662 fsp->initial_delete_on_close = True;
5666 return NT_STATUS_OK;
5671 if (errno == ENOTDIR || errno == EISDIR) {
5672 status = NT_STATUS_OBJECT_NAME_COLLISION;
5674 status = map_nt_error_from_unix(errno);
5677 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5678 nt_errstr(status), fsp->fsp_name,newname));
5683 /****************************************************************************
5684 The guts of the rename command, split out so it may be called by the NT SMB
5686 ****************************************************************************/
5688 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5689 connection_struct *conn,
5690 struct smb_request *req,
5691 const char *name_in,
5692 const char *newname_in,
5694 bool replace_if_exists,
5697 uint32_t access_mask)
5699 char *directory = NULL;
5701 char *last_component_src = NULL;
5702 char *last_component_dest = NULL;
5704 char *newname = NULL;
5707 NTSTATUS status = NT_STATUS_OK;
5708 SMB_STRUCT_STAT sbuf1, sbuf2;
5709 struct smb_Dir *dir_hnd = NULL;
5712 int create_options = 0;
5717 status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5718 &last_component_src, &sbuf1);
5719 if (!NT_STATUS_IS_OK(status)) {
5723 status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5724 &last_component_dest, &sbuf2);
5725 if (!NT_STATUS_IS_OK(status)) {
5730 * Split the old name into directory and last component
5731 * strings. Note that unix_convert may have stripped off a
5732 * leading ./ from both name and newname if the rename is
5733 * at the root of the share. We need to make sure either both
5734 * name and newname contain a / character or neither of them do
5735 * as this is checked in resolve_wildcards().
5738 p = strrchr_m(name,'/');
5740 directory = talloc_strdup(ctx, ".");
5742 return NT_STATUS_NO_MEMORY;
5747 directory = talloc_strdup(ctx, name);
5749 return NT_STATUS_NO_MEMORY;
5752 *p = '/'; /* Replace needed for exceptional test below. */
5756 * We should only check the mangled cache
5757 * here if unix_convert failed. This means
5758 * that the path in 'mask' doesn't exist
5759 * on the file system and so we need to look
5760 * for a possible mangle. This patch from
5761 * Tine Smukavec <valentin.smukavec@hermes.si>.
5764 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5765 char *new_mask = NULL;
5766 mangle_lookup_name_from_8_3(ctx,
5775 if (!src_has_wild) {
5779 * No wildcards - just process the one file.
5781 bool is_short_name = mangle_is_8_3(name, True, conn->params);
5783 /* Add a terminating '/' to the directory name. */
5784 directory = talloc_asprintf_append(directory,
5788 return NT_STATUS_NO_MEMORY;
5791 /* Ensure newname contains a '/' also */
5792 if(strrchr_m(newname,'/') == 0) {
5793 newname = talloc_asprintf(ctx,
5797 return NT_STATUS_NO_MEMORY;
5801 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5802 "case_preserve = %d, short case preserve = %d, "
5803 "directory = %s, newname = %s, "
5804 "last_component_dest = %s, is_8_3 = %d\n",
5805 conn->case_sensitive, conn->case_preserve,
5806 conn->short_case_preserve, directory,
5807 newname, last_component_dest, is_short_name));
5809 /* The dest name still may have wildcards. */
5810 if (dest_has_wild) {
5811 char *mod_newname = NULL;
5812 if (!resolve_wildcards(ctx,
5813 directory,newname,&mod_newname)) {
5814 DEBUG(6, ("rename_internals: resolve_wildcards "
5818 return NT_STATUS_NO_MEMORY;
5820 newname = mod_newname;
5824 SMB_VFS_STAT(conn, directory, &sbuf1);
5826 if (S_ISDIR(sbuf1.st_mode)) {
5827 create_options |= FILE_DIRECTORY_FILE;
5830 status = SMB_VFS_CREATE_FILE(
5833 0, /* root_dir_fid */
5834 directory, /* fname */
5835 0, /* create_file_flags */
5836 access_mask, /* access_mask */
5837 (FILE_SHARE_READ | /* share_access */
5839 FILE_OPEN, /* create_disposition*/
5840 create_options, /* create_options */
5841 0, /* file_attributes */
5842 0, /* oplock_request */
5843 0, /* allocation_size */
5848 &sbuf1); /* psbuf */
5850 if (!NT_STATUS_IS_OK(status)) {
5851 DEBUG(3, ("Could not open rename source %s: %s\n",
5852 directory, nt_errstr(status)));
5856 status = rename_internals_fsp(conn, fsp, newname,
5857 last_component_dest,
5858 attrs, replace_if_exists);
5860 close_file(req, fsp, NORMAL_CLOSE);
5862 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5863 nt_errstr(status), directory,newname));
5869 * Wildcards - process each file that matches.
5871 if (strequal(mask,"????????.???")) {
5876 status = check_name(conn, directory);
5877 if (!NT_STATUS_IS_OK(status)) {
5881 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
5882 if (dir_hnd == NULL) {
5883 return map_nt_error_from_unix(errno);
5886 status = NT_STATUS_NO_SUCH_FILE;
5888 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5889 * - gentest fix. JRA
5892 while ((dname = ReadDirName(dir_hnd, &offset))) {
5893 files_struct *fsp = NULL;
5895 char *destname = NULL;
5896 bool sysdir_entry = False;
5898 /* Quick check for "." and ".." */
5899 if (ISDOT(dname) || ISDOTDOT(dname)) {
5901 sysdir_entry = True;
5907 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5911 if(!mask_match(dname, mask, conn->case_sensitive)) {
5916 status = NT_STATUS_OBJECT_NAME_INVALID;
5920 fname = talloc_asprintf(ctx,
5925 return NT_STATUS_NO_MEMORY;
5928 if (!resolve_wildcards(ctx,
5929 fname,newname,&destname)) {
5930 DEBUG(6, ("resolve_wildcards %s %s failed\n",
5936 return NT_STATUS_NO_MEMORY;
5940 SMB_VFS_STAT(conn, fname, &sbuf1);
5944 if (S_ISDIR(sbuf1.st_mode)) {
5945 create_options |= FILE_DIRECTORY_FILE;
5948 status = SMB_VFS_CREATE_FILE(
5951 0, /* root_dir_fid */
5953 0, /* create_file_flags */
5954 access_mask, /* access_mask */
5955 (FILE_SHARE_READ | /* share_access */
5957 FILE_OPEN, /* create_disposition*/
5958 create_options, /* create_options */
5959 0, /* file_attributes */
5960 0, /* oplock_request */
5961 0, /* allocation_size */
5966 &sbuf1); /* psbuf */
5968 if (!NT_STATUS_IS_OK(status)) {
5969 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
5970 "returned %s rename %s -> %s\n",
5971 nt_errstr(status), directory, newname));
5975 status = rename_internals_fsp(conn, fsp, destname, dname,
5976 attrs, replace_if_exists);
5978 close_file(req, fsp, NORMAL_CLOSE);
5980 if (!NT_STATUS_IS_OK(status)) {
5981 DEBUG(3, ("rename_internals_fsp returned %s for "
5982 "rename %s -> %s\n", nt_errstr(status),
5983 directory, newname));
5989 DEBUG(3,("rename_internals: doing rename on %s -> "
5990 "%s\n",fname,destname));
5993 TALLOC_FREE(destname);
5995 TALLOC_FREE(dir_hnd);
5997 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
5998 status = map_nt_error_from_unix(errno);
6004 /****************************************************************************
6006 ****************************************************************************/
6008 void reply_mv(struct smb_request *req)
6010 connection_struct *conn = req->conn;
6012 char *newname = NULL;
6016 bool src_has_wcard = False;
6017 bool dest_has_wcard = False;
6018 TALLOC_CTX *ctx = talloc_tos();
6020 START_PROFILE(SMBmv);
6023 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6028 attrs = SVAL(req->vwv+0, 0);
6030 p = (const char *)req->buf + 1;
6031 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6032 &status, &src_has_wcard);
6033 if (!NT_STATUS_IS_OK(status)) {
6034 reply_nterror(req, status);
6039 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6040 &status, &dest_has_wcard);
6041 if (!NT_STATUS_IS_OK(status)) {
6042 reply_nterror(req, status);
6047 status = resolve_dfspath_wcard(ctx, conn,
6048 req->flags2 & FLAGS2_DFS_PATHNAMES,
6052 if (!NT_STATUS_IS_OK(status)) {
6053 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6054 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6055 ERRSRV, ERRbadpath);
6059 reply_nterror(req, status);
6064 status = resolve_dfspath_wcard(ctx, conn,
6065 req->flags2 & FLAGS2_DFS_PATHNAMES,
6069 if (!NT_STATUS_IS_OK(status)) {
6070 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6071 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6072 ERRSRV, ERRbadpath);
6076 reply_nterror(req, status);
6081 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6083 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6084 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6085 if (!NT_STATUS_IS_OK(status)) {
6086 if (open_was_deferred(req->mid)) {
6087 /* We have re-scheduled this call. */
6091 reply_nterror(req, status);
6096 reply_outbuf(req, 0, 0);
6102 /*******************************************************************
6103 Copy a file as part of a reply_copy.
6104 ******************************************************************/
6107 * TODO: check error codes on all callers
6110 NTSTATUS copy_file(TALLOC_CTX *ctx,
6111 connection_struct *conn,
6116 bool target_is_directory)
6118 SMB_STRUCT_STAT src_sbuf, sbuf2;
6120 files_struct *fsp1,*fsp2;
6123 uint32 new_create_disposition;
6126 dest = talloc_strdup(ctx, dest1);
6128 return NT_STATUS_NO_MEMORY;
6130 if (target_is_directory) {
6131 const char *p = strrchr_m(src,'/');
6137 dest = talloc_asprintf_append(dest,
6141 return NT_STATUS_NO_MEMORY;
6145 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6147 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6150 if (!target_is_directory && count) {
6151 new_create_disposition = FILE_OPEN;
6153 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6154 NULL, NULL, &new_create_disposition, NULL)) {
6156 return NT_STATUS_INVALID_PARAMETER;
6160 status = SMB_VFS_CREATE_FILE(
6163 0, /* root_dir_fid */
6165 0, /* create_file_flags */
6166 FILE_GENERIC_READ, /* access_mask */
6167 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6168 FILE_OPEN, /* create_disposition*/
6169 0, /* create_options */
6170 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6171 INTERNAL_OPEN_ONLY, /* oplock_request */
6172 0, /* allocation_size */
6177 &src_sbuf); /* psbuf */
6179 if (!NT_STATUS_IS_OK(status)) {
6184 dosattrs = dos_mode(conn, src, &src_sbuf);
6185 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6186 ZERO_STRUCTP(&sbuf2);
6189 status = SMB_VFS_CREATE_FILE(
6192 0, /* root_dir_fid */
6194 0, /* create_file_flags */
6195 FILE_GENERIC_WRITE, /* access_mask */
6196 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6197 new_create_disposition, /* create_disposition*/
6198 0, /* create_options */
6199 dosattrs, /* file_attributes */
6200 INTERNAL_OPEN_ONLY, /* oplock_request */
6201 0, /* allocation_size */
6206 &sbuf2); /* psbuf */
6210 if (!NT_STATUS_IS_OK(status)) {
6211 close_file(NULL, fsp1, ERROR_CLOSE);
6215 if ((ofun&3) == 1) {
6216 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6217 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6219 * Stop the copy from occurring.
6222 src_sbuf.st_size = 0;
6226 if (src_sbuf.st_size) {
6227 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6230 close_file(NULL, fsp1, NORMAL_CLOSE);
6232 /* Ensure the modtime is set correctly on the destination file. */
6233 set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
6236 * As we are opening fsp1 read-only we only expect
6237 * an error on close on fsp2 if we are out of space.
6238 * Thus we don't look at the error return from the
6241 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6243 if (!NT_STATUS_IS_OK(status)) {
6247 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6248 return NT_STATUS_DISK_FULL;
6251 return NT_STATUS_OK;
6254 /****************************************************************************
6255 Reply to a file copy.
6256 ****************************************************************************/
6258 void reply_copy(struct smb_request *req)
6260 connection_struct *conn = req->conn;
6262 char *newname = NULL;
6263 char *directory = NULL;
6264 const char *mask = NULL;
6265 const char mask_star[] = "*";
6268 int error = ERRnoaccess;
6273 bool target_is_directory=False;
6274 bool source_has_wild = False;
6275 bool dest_has_wild = False;
6276 SMB_STRUCT_STAT sbuf1, sbuf2;
6278 TALLOC_CTX *ctx = talloc_tos();
6280 START_PROFILE(SMBcopy);
6283 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6284 END_PROFILE(SMBcopy);
6288 tid2 = SVAL(req->vwv+0, 0);
6289 ofun = SVAL(req->vwv+1, 0);
6290 flags = SVAL(req->vwv+2, 0);
6292 p = (const char *)req->buf;
6293 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6294 &status, &source_has_wild);
6295 if (!NT_STATUS_IS_OK(status)) {
6296 reply_nterror(req, status);
6297 END_PROFILE(SMBcopy);
6300 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6301 &status, &dest_has_wild);
6302 if (!NT_STATUS_IS_OK(status)) {
6303 reply_nterror(req, status);
6304 END_PROFILE(SMBcopy);
6308 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6310 if (tid2 != conn->cnum) {
6311 /* can't currently handle inter share copies XXXX */
6312 DEBUG(3,("Rejecting inter-share copy\n"));
6313 reply_doserror(req, ERRSRV, ERRinvdevice);
6314 END_PROFILE(SMBcopy);
6318 status = resolve_dfspath_wcard(ctx, conn,
6319 req->flags2 & FLAGS2_DFS_PATHNAMES,
6323 if (!NT_STATUS_IS_OK(status)) {
6324 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6325 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6326 ERRSRV, ERRbadpath);
6327 END_PROFILE(SMBcopy);
6330 reply_nterror(req, status);
6331 END_PROFILE(SMBcopy);
6335 status = resolve_dfspath_wcard(ctx, conn,
6336 req->flags2 & FLAGS2_DFS_PATHNAMES,
6340 if (!NT_STATUS_IS_OK(status)) {
6341 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6342 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6343 ERRSRV, ERRbadpath);
6344 END_PROFILE(SMBcopy);
6347 reply_nterror(req, status);
6348 END_PROFILE(SMBcopy);
6352 status = unix_convert(ctx, conn, name, source_has_wild,
6353 &name, NULL, &sbuf1);
6354 if (!NT_STATUS_IS_OK(status)) {
6355 reply_nterror(req, status);
6356 END_PROFILE(SMBcopy);
6360 status = unix_convert(ctx, conn, newname, dest_has_wild,
6361 &newname, NULL, &sbuf2);
6362 if (!NT_STATUS_IS_OK(status)) {
6363 reply_nterror(req, status);
6364 END_PROFILE(SMBcopy);
6368 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6370 if ((flags&1) && target_is_directory) {
6371 reply_doserror(req, ERRDOS, ERRbadfile);
6372 END_PROFILE(SMBcopy);
6376 if ((flags&2) && !target_is_directory) {
6377 reply_doserror(req, ERRDOS, ERRbadpath);
6378 END_PROFILE(SMBcopy);
6382 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6383 /* wants a tree copy! XXXX */
6384 DEBUG(3,("Rejecting tree copy\n"));
6385 reply_doserror(req, ERRSRV, ERRerror);
6386 END_PROFILE(SMBcopy);
6390 p = strrchr_m(name,'/');
6392 directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
6395 directory = talloc_strdup(ctx, "./");
6400 reply_nterror(req, NT_STATUS_NO_MEMORY);
6401 END_PROFILE(SMBcopy);
6406 * We should only check the mangled cache
6407 * here if unix_convert failed. This means
6408 * that the path in 'mask' doesn't exist
6409 * on the file system and so we need to look
6410 * for a possible mangle. This patch from
6411 * Tine Smukavec <valentin.smukavec@hermes.si>.
6414 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6415 char *new_mask = NULL;
6416 mangle_lookup_name_from_8_3(ctx,
6425 if (!source_has_wild) {
6426 directory = talloc_asprintf_append(directory,
6429 if (dest_has_wild) {
6430 char *mod_newname = NULL;
6431 if (!resolve_wildcards(ctx,
6432 directory,newname,&mod_newname)) {
6433 reply_nterror(req, NT_STATUS_NO_MEMORY);
6434 END_PROFILE(SMBcopy);
6437 newname = mod_newname;
6440 status = check_name(conn, directory);
6441 if (!NT_STATUS_IS_OK(status)) {
6442 reply_nterror(req, status);
6443 END_PROFILE(SMBcopy);
6447 status = check_name(conn, newname);
6448 if (!NT_STATUS_IS_OK(status)) {
6449 reply_nterror(req, status);
6450 END_PROFILE(SMBcopy);
6454 status = copy_file(ctx,conn,directory,newname,ofun,
6455 count,target_is_directory);
6457 if(!NT_STATUS_IS_OK(status)) {
6458 reply_nterror(req, status);
6459 END_PROFILE(SMBcopy);
6465 struct smb_Dir *dir_hnd = NULL;
6466 const char *dname = NULL;
6469 if (strequal(mask,"????????.???")) {
6473 status = check_name(conn, directory);
6474 if (!NT_STATUS_IS_OK(status)) {
6475 reply_nterror(req, status);
6476 END_PROFILE(SMBcopy);
6480 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6481 if (dir_hnd == NULL) {
6482 status = map_nt_error_from_unix(errno);
6483 reply_nterror(req, status);
6484 END_PROFILE(SMBcopy);
6490 while ((dname = ReadDirName(dir_hnd, &offset))) {
6491 char *destname = NULL;
6494 if (ISDOT(dname) || ISDOTDOT(dname)) {
6498 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6502 if(!mask_match(dname, mask, conn->case_sensitive)) {
6506 error = ERRnoaccess;
6507 fname = talloc_asprintf(ctx,
6512 TALLOC_FREE(dir_hnd);
6513 reply_nterror(req, NT_STATUS_NO_MEMORY);
6514 END_PROFILE(SMBcopy);
6518 if (!resolve_wildcards(ctx,
6519 fname,newname,&destname)) {
6523 TALLOC_FREE(dir_hnd);
6524 reply_nterror(req, NT_STATUS_NO_MEMORY);
6525 END_PROFILE(SMBcopy);
6529 status = check_name(conn, fname);
6530 if (!NT_STATUS_IS_OK(status)) {
6531 TALLOC_FREE(dir_hnd);
6532 reply_nterror(req, status);
6533 END_PROFILE(SMBcopy);
6537 status = check_name(conn, destname);
6538 if (!NT_STATUS_IS_OK(status)) {
6539 TALLOC_FREE(dir_hnd);
6540 reply_nterror(req, status);
6541 END_PROFILE(SMBcopy);
6545 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6547 status = copy_file(ctx,conn,fname,destname,ofun,
6548 count,target_is_directory);
6549 if (NT_STATUS_IS_OK(status)) {
6553 TALLOC_FREE(destname);
6555 TALLOC_FREE(dir_hnd);
6560 /* Error on close... */
6562 reply_unixerror(req, ERRHRD, ERRgeneral);
6563 END_PROFILE(SMBcopy);
6567 reply_doserror(req, ERRDOS, error);
6568 END_PROFILE(SMBcopy);
6572 reply_outbuf(req, 1, 0);
6573 SSVAL(req->outbuf,smb_vwv0,count);
6575 END_PROFILE(SMBcopy);
6580 #define DBGC_CLASS DBGC_LOCKING
6582 /****************************************************************************
6583 Get a lock pid, dealing with large count requests.
6584 ****************************************************************************/
6586 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6587 bool large_file_format)
6589 if(!large_file_format)
6590 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6592 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6595 /****************************************************************************
6596 Get a lock count, dealing with large count requests.
6597 ****************************************************************************/
6599 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6600 bool large_file_format)
6604 if(!large_file_format) {
6605 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6608 #if defined(HAVE_LONGLONG)
6609 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6610 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6611 #else /* HAVE_LONGLONG */
6614 * NT4.x seems to be broken in that it sends large file (64 bit)
6615 * lockingX calls even if the CAP_LARGE_FILES was *not*
6616 * negotiated. For boxes without large unsigned ints truncate the
6617 * lock count by dropping the top 32 bits.
6620 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6621 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6622 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6623 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6624 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6627 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6628 #endif /* HAVE_LONGLONG */
6634 #if !defined(HAVE_LONGLONG)
6635 /****************************************************************************
6636 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6637 ****************************************************************************/
6639 static uint32 map_lock_offset(uint32 high, uint32 low)
6643 uint32 highcopy = high;
6646 * Try and find out how many significant bits there are in high.
6649 for(i = 0; highcopy; i++)
6653 * We use 31 bits not 32 here as POSIX
6654 * lock offsets may not be negative.
6657 mask = (~0) << (31 - i);
6660 return 0; /* Fail. */
6666 #endif /* !defined(HAVE_LONGLONG) */
6668 /****************************************************************************
6669 Get a lock offset, dealing with large offset requests.
6670 ****************************************************************************/
6672 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6673 bool large_file_format, bool *err)
6675 uint64_t offset = 0;
6679 if(!large_file_format) {
6680 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6683 #if defined(HAVE_LONGLONG)
6684 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6685 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6686 #else /* HAVE_LONGLONG */
6689 * NT4.x seems to be broken in that it sends large file (64 bit)
6690 * lockingX calls even if the CAP_LARGE_FILES was *not*
6691 * negotiated. For boxes without large unsigned ints mangle the
6692 * lock offset by mapping the top 32 bits onto the lower 32.
6695 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6696 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6697 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6700 if((new_low = map_lock_offset(high, low)) == 0) {
6702 return (uint64_t)-1;
6705 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6706 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6707 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6708 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6711 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6712 #endif /* HAVE_LONGLONG */
6718 /****************************************************************************
6719 Reply to a lockingX request.
6720 ****************************************************************************/
6722 void reply_lockingX(struct smb_request *req)
6724 connection_struct *conn = req->conn;
6726 unsigned char locktype;
6727 unsigned char oplocklevel;
6730 uint64_t count = 0, offset = 0;
6734 const uint8_t *data;
6735 bool large_file_format;
6737 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6739 START_PROFILE(SMBlockingX);
6742 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6743 END_PROFILE(SMBlockingX);
6747 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
6748 locktype = CVAL(req->vwv+3, 0);
6749 oplocklevel = CVAL(req->vwv+3, 1);
6750 num_ulocks = SVAL(req->vwv+6, 0);
6751 num_locks = SVAL(req->vwv+7, 0);
6752 lock_timeout = IVAL(req->vwv+4, 0);
6753 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6755 if (!check_fsp(conn, req, fsp)) {
6756 END_PROFILE(SMBlockingX);
6762 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6763 /* we don't support these - and CANCEL_LOCK makes w2k
6764 and XP reboot so I don't really want to be
6765 compatible! (tridge) */
6766 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6767 END_PROFILE(SMBlockingX);
6771 /* Check if this is an oplock break on a file
6772 we have granted an oplock on.
6774 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6775 /* Client can insist on breaking to none. */
6776 bool break_to_none = (oplocklevel == 0);
6779 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6780 "for fnum = %d\n", (unsigned int)oplocklevel,
6784 * Make sure we have granted an exclusive or batch oplock on
6788 if (fsp->oplock_type == 0) {
6790 /* The Samba4 nbench simulator doesn't understand
6791 the difference between break to level2 and break
6792 to none from level2 - it sends oplock break
6793 replies in both cases. Don't keep logging an error
6794 message here - just ignore it. JRA. */
6796 DEBUG(5,("reply_lockingX: Error : oplock break from "
6797 "client for fnum = %d (oplock=%d) and no "
6798 "oplock granted on this file (%s).\n",
6799 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
6801 /* if this is a pure oplock break request then don't
6803 if (num_locks == 0 && num_ulocks == 0) {
6804 END_PROFILE(SMBlockingX);
6807 END_PROFILE(SMBlockingX);
6808 reply_doserror(req, ERRDOS, ERRlock);
6813 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6815 result = remove_oplock(fsp);
6817 result = downgrade_oplock(fsp);
6821 DEBUG(0, ("reply_lockingX: error in removing "
6822 "oplock on file %s\n", fsp->fsp_name));
6823 /* Hmmm. Is this panic justified? */
6824 smb_panic("internal tdb error");
6827 reply_to_oplock_break_requests(fsp);
6829 /* if this is a pure oplock break request then don't send a
6831 if (num_locks == 0 && num_ulocks == 0) {
6832 /* Sanity check - ensure a pure oplock break is not a
6834 if(CVAL(req->vwv+0, 0) != 0xff)
6835 DEBUG(0,("reply_lockingX: Error : pure oplock "
6836 "break is a chained %d request !\n",
6837 (unsigned int)CVAL(req->vwv+0, 0)));
6838 END_PROFILE(SMBlockingX);
6844 * We do this check *after* we have checked this is not a oplock break
6845 * response message. JRA.
6848 release_level_2_oplocks_on_change(fsp);
6851 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6852 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6853 END_PROFILE(SMBlockingX);
6857 /* Data now points at the beginning of the list
6858 of smb_unlkrng structs */
6859 for(i = 0; i < (int)num_ulocks; i++) {
6860 lock_pid = get_lock_pid( data, i, large_file_format);
6861 count = get_lock_count( data, i, large_file_format);
6862 offset = get_lock_offset( data, i, large_file_format, &err);
6865 * There is no error code marked "stupid client bug".... :-).
6868 END_PROFILE(SMBlockingX);
6869 reply_doserror(req, ERRDOS, ERRnoaccess);
6873 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6874 "pid %u, file %s\n", (double)offset, (double)count,
6875 (unsigned int)lock_pid, fsp->fsp_name ));
6877 status = do_unlock(smbd_messaging_context(),
6884 if (NT_STATUS_V(status)) {
6885 END_PROFILE(SMBlockingX);
6886 reply_nterror(req, status);
6891 /* Setup the timeout in seconds. */
6893 if (!lp_blocking_locks(SNUM(conn))) {
6897 /* Now do any requested locks */
6898 data += ((large_file_format ? 20 : 10)*num_ulocks);
6900 /* Data now points at the beginning of the list
6901 of smb_lkrng structs */
6903 for(i = 0; i < (int)num_locks; i++) {
6904 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
6905 READ_LOCK:WRITE_LOCK);
6906 lock_pid = get_lock_pid( data, i, large_file_format);
6907 count = get_lock_count( data, i, large_file_format);
6908 offset = get_lock_offset( data, i, large_file_format, &err);
6911 * There is no error code marked "stupid client bug".... :-).
6914 END_PROFILE(SMBlockingX);
6915 reply_doserror(req, ERRDOS, ERRnoaccess);
6919 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6920 "%u, file %s timeout = %d\n", (double)offset,
6921 (double)count, (unsigned int)lock_pid,
6922 fsp->fsp_name, (int)lock_timeout ));
6924 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6925 if (lp_blocking_locks(SNUM(conn))) {
6927 /* Schedule a message to ourselves to
6928 remove the blocking lock record and
6929 return the right error. */
6931 if (!blocking_lock_cancel(fsp,
6937 NT_STATUS_FILE_LOCK_CONFLICT)) {
6938 END_PROFILE(SMBlockingX);
6943 ERRcancelviolation));
6947 /* Remove a matching pending lock. */
6948 status = do_lock_cancel(fsp,
6954 bool blocking_lock = lock_timeout ? True : False;
6955 bool defer_lock = False;
6956 struct byte_range_lock *br_lck;
6957 uint32 block_smbpid;
6959 br_lck = do_lock(smbd_messaging_context(),
6970 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6971 /* Windows internal resolution for blocking locks seems
6972 to be about 200ms... Don't wait for less than that. JRA. */
6973 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
6974 lock_timeout = lp_lock_spin_time();
6979 /* This heuristic seems to match W2K3 very well. If a
6980 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
6981 it pretends we asked for a timeout of between 150 - 300 milliseconds as
6982 far as I can tell. Replacement for do_lock_spin(). JRA. */
6984 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
6985 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
6987 lock_timeout = lp_lock_spin_time();
6990 if (br_lck && defer_lock) {
6992 * A blocking lock was requested. Package up
6993 * this smb into a queued request and push it
6994 * onto the blocking lock queue.
6996 if(push_blocking_lock_request(br_lck,
7007 TALLOC_FREE(br_lck);
7008 END_PROFILE(SMBlockingX);
7013 TALLOC_FREE(br_lck);
7016 if (NT_STATUS_V(status)) {
7017 END_PROFILE(SMBlockingX);
7018 reply_nterror(req, status);
7023 /* If any of the above locks failed, then we must unlock
7024 all of the previous locks (X/Open spec). */
7026 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7030 * Ensure we don't do a remove on the lock that just failed,
7031 * as under POSIX rules, if we have a lock already there, we
7032 * will delete it (and we shouldn't) .....
7034 for(i--; i >= 0; i--) {
7035 lock_pid = get_lock_pid( data, i, large_file_format);
7036 count = get_lock_count( data, i, large_file_format);
7037 offset = get_lock_offset( data, i, large_file_format,
7041 * There is no error code marked "stupid client
7045 END_PROFILE(SMBlockingX);
7046 reply_doserror(req, ERRDOS, ERRnoaccess);
7050 do_unlock(smbd_messaging_context(),
7057 END_PROFILE(SMBlockingX);
7058 reply_nterror(req, status);
7062 reply_outbuf(req, 2, 0);
7064 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7065 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7067 END_PROFILE(SMBlockingX);
7072 #define DBGC_CLASS DBGC_ALL
7074 /****************************************************************************
7075 Reply to a SMBreadbmpx (read block multiplex) request.
7076 Always reply with an error, if someone has a platform really needs this,
7077 please contact vl@samba.org
7078 ****************************************************************************/
7080 void reply_readbmpx(struct smb_request *req)
7082 START_PROFILE(SMBreadBmpx);
7083 reply_doserror(req, ERRSRV, ERRuseSTD);
7084 END_PROFILE(SMBreadBmpx);
7088 /****************************************************************************
7089 Reply to a SMBreadbs (read block multiplex secondary) request.
7090 Always reply with an error, if someone has a platform really needs this,
7091 please contact vl@samba.org
7092 ****************************************************************************/
7094 void reply_readbs(struct smb_request *req)
7096 START_PROFILE(SMBreadBs);
7097 reply_doserror(req, ERRSRV, ERRuseSTD);
7098 END_PROFILE(SMBreadBs);
7102 /****************************************************************************
7103 Reply to a SMBsetattrE.
7104 ****************************************************************************/
7106 void reply_setattrE(struct smb_request *req)
7108 connection_struct *conn = req->conn;
7109 struct timespec ts[2];
7111 SMB_STRUCT_STAT sbuf;
7114 START_PROFILE(SMBsetattrE);
7117 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7118 END_PROFILE(SMBsetattrE);
7122 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7124 if(!fsp || (fsp->conn != conn)) {
7125 reply_doserror(req, ERRDOS, ERRbadfid);
7126 END_PROFILE(SMBsetattrE);
7132 * Convert the DOS times into unix times. Ignore create
7133 * time as UNIX can't set this.
7136 ts[0] = convert_time_t_to_timespec(
7137 srv_make_unix_date2(req->vwv+3)); /* atime. */
7138 ts[1] = convert_time_t_to_timespec(
7139 srv_make_unix_date2(req->vwv+5)); /* mtime. */
7141 reply_outbuf(req, 0, 0);
7144 * Patch from Ray Frush <frush@engr.colostate.edu>
7145 * Sometimes times are sent as zero - ignore them.
7148 /* Ensure we have a valid stat struct for the source. */
7149 if (fsp->fh->fd != -1) {
7150 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7151 status = map_nt_error_from_unix(errno);
7152 reply_nterror(req, status);
7153 END_PROFILE(SMBsetattrE);
7157 if (SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf) == -1) {
7158 status = map_nt_error_from_unix(errno);
7159 reply_nterror(req, status);
7160 END_PROFILE(SMBsetattrE);
7165 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7167 if (!NT_STATUS_IS_OK(status)) {
7168 reply_doserror(req, ERRDOS, ERRnoaccess);
7169 END_PROFILE(SMBsetattrE);
7173 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
7175 (unsigned int)ts[0].tv_sec,
7176 (unsigned int)ts[1].tv_sec));
7178 END_PROFILE(SMBsetattrE);
7183 /* Back from the dead for OS/2..... JRA. */
7185 /****************************************************************************
7186 Reply to a SMBwritebmpx (write block multiplex primary) request.
7187 Always reply with an error, if someone has a platform really needs this,
7188 please contact vl@samba.org
7189 ****************************************************************************/
7191 void reply_writebmpx(struct smb_request *req)
7193 START_PROFILE(SMBwriteBmpx);
7194 reply_doserror(req, ERRSRV, ERRuseSTD);
7195 END_PROFILE(SMBwriteBmpx);
7199 /****************************************************************************
7200 Reply to a SMBwritebs (write block multiplex secondary) request.
7201 Always reply with an error, if someone has a platform really needs this,
7202 please contact vl@samba.org
7203 ****************************************************************************/
7205 void reply_writebs(struct smb_request *req)
7207 START_PROFILE(SMBwriteBs);
7208 reply_doserror(req, ERRSRV, ERRuseSTD);
7209 END_PROFILE(SMBwriteBs);
7213 /****************************************************************************
7214 Reply to a SMBgetattrE.
7215 ****************************************************************************/
7217 void reply_getattrE(struct smb_request *req)
7219 connection_struct *conn = req->conn;
7220 SMB_STRUCT_STAT sbuf;
7223 struct timespec create_ts;
7225 START_PROFILE(SMBgetattrE);
7228 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7229 END_PROFILE(SMBgetattrE);
7233 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7235 if(!fsp || (fsp->conn != conn)) {
7236 reply_doserror(req, ERRDOS, ERRbadfid);
7237 END_PROFILE(SMBgetattrE);
7241 /* Do an fstat on this file */
7242 if(fsp_stat(fsp, &sbuf)) {
7243 reply_unixerror(req, ERRDOS, ERRnoaccess);
7244 END_PROFILE(SMBgetattrE);
7248 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7251 * Convert the times into dos times. Set create
7252 * date to be last modify date as UNIX doesn't save
7256 reply_outbuf(req, 11, 0);
7258 create_ts = get_create_timespec(&sbuf,
7259 lp_fake_dir_create_times(SNUM(conn)));
7260 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7261 srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7262 /* Should we check pending modtime here ? JRA */
7263 srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7266 SIVAL(req->outbuf, smb_vwv6, 0);
7267 SIVAL(req->outbuf, smb_vwv8, 0);
7269 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
7270 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7271 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7273 SSVAL(req->outbuf,smb_vwv10, mode);
7275 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7277 END_PROFILE(SMBgetattrE);