2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "smbd/globals.h"
30 extern enum protocol_types Protocol;
32 /****************************************************************************
33 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
34 path or anything including wildcards.
35 We're assuming here that '/' is not the second byte in any multibyte char
36 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
38 ****************************************************************************/
40 /* Custom version for processing POSIX paths. */
41 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
43 static NTSTATUS check_path_syntax_internal(char *path,
45 bool *p_last_component_contains_wcard)
49 NTSTATUS ret = NT_STATUS_OK;
50 bool start_of_name_component = True;
51 bool stream_started = false;
53 *p_last_component_contains_wcard = False;
60 return NT_STATUS_OBJECT_NAME_INVALID;
63 return NT_STATUS_OBJECT_NAME_INVALID;
65 if (strchr_m(&s[1], ':')) {
66 return NT_STATUS_OBJECT_NAME_INVALID;
68 if (StrCaseCmp(s, ":$DATA") != 0) {
69 return NT_STATUS_INVALID_PARAMETER;
75 if (!stream_started && *s == ':') {
76 if (*p_last_component_contains_wcard) {
77 return NT_STATUS_OBJECT_NAME_INVALID;
79 /* stream names allow more characters than file names */
80 stream_started = true;
81 start_of_name_component = false;
85 return NT_STATUS_OBJECT_NAME_INVALID;
89 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
91 * Safe to assume is not the second part of a mb char
92 * as this is handled below.
94 /* Eat multiple '/' or '\\' */
95 while (IS_PATH_SEP(*s,posix_path)) {
98 if ((d != path) && (*s != '\0')) {
99 /* We only care about non-leading or trailing '/' or '\\' */
103 start_of_name_component = True;
105 *p_last_component_contains_wcard = False;
109 if (start_of_name_component) {
110 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
111 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
114 * No mb char starts with '.' so we're safe checking the directory separator here.
117 /* If we just added a '/' - delete it */
118 if ((d > path) && (*(d-1) == '/')) {
123 /* Are we at the start ? Can't go back further if so. */
125 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
128 /* Go back one level... */
129 /* We know this is safe as '/' cannot be part of a mb sequence. */
130 /* NOTE - if this assumption is invalid we are not in good shape... */
131 /* Decrement d first as d points to the *next* char to write into. */
132 for (d--; d > path; d--) {
136 s += 2; /* Else go past the .. */
137 /* We're still at the start of a name component, just the previous one. */
140 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
152 if (*s <= 0x1f || *s == '|') {
153 return NT_STATUS_OBJECT_NAME_INVALID;
161 *p_last_component_contains_wcard = True;
170 /* Get the size of the next MB character. */
171 next_codepoint(s,&siz);
189 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
191 return NT_STATUS_INVALID_PARAMETER;
194 start_of_name_component = False;
202 /****************************************************************************
203 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
204 No wildcards allowed.
205 ****************************************************************************/
207 NTSTATUS check_path_syntax(char *path)
210 return check_path_syntax_internal(path, False, &ignore);
213 /****************************************************************************
214 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
215 Wildcards allowed - p_contains_wcard returns true if the last component contained
217 ****************************************************************************/
219 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
221 return check_path_syntax_internal(path, False, p_contains_wcard);
224 /****************************************************************************
225 Check the path for a POSIX client.
226 We're assuming here that '/' is not the second byte in any multibyte char
227 set (a safe assumption).
228 ****************************************************************************/
230 NTSTATUS check_path_syntax_posix(char *path)
233 return check_path_syntax_internal(path, True, &ignore);
236 /****************************************************************************
237 Pull a string and check the path allowing a wilcard - provide for error return.
238 ****************************************************************************/
240 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
241 const char *base_ptr,
248 bool *contains_wcard)
254 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
258 *err = NT_STATUS_INVALID_PARAMETER;
262 *contains_wcard = False;
264 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
266 * For a DFS path the function parse_dfs_path()
267 * will do the path processing, just make a copy.
273 if (lp_posix_pathnames()) {
274 *err = check_path_syntax_posix(*pp_dest);
276 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
282 /****************************************************************************
283 Pull a string and check the path - provide for error return.
284 ****************************************************************************/
286 size_t srvstr_get_path(TALLOC_CTX *ctx,
287 const char *base_ptr,
296 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
297 src_len, flags, err, &ignore);
300 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
301 char **pp_dest, const char *src, int flags,
302 NTSTATUS *err, bool *contains_wcard)
304 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
305 pp_dest, src, smbreq_bufrem(req, src),
306 flags, err, contains_wcard);
309 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
310 char **pp_dest, const char *src, int flags,
314 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
315 flags, err, &ignore);
318 /****************************************************************************
319 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
320 ****************************************************************************/
322 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
325 if (!(fsp) || !(conn)) {
326 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
329 if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
330 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
336 /****************************************************************************
337 Check if we have a correct fsp pointing to a file.
338 ****************************************************************************/
340 bool check_fsp(connection_struct *conn, struct smb_request *req,
343 if (!check_fsp_open(conn, req, fsp)) {
346 if ((fsp)->is_directory) {
347 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
350 if ((fsp)->fh->fd == -1) {
351 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
354 (fsp)->num_smb_operations++;
358 /****************************************************************************
359 Check if we have a correct fsp pointing to a quota fake file. Replacement for
360 the CHECK_NTQUOTA_HANDLE_OK macro.
361 ****************************************************************************/
363 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
366 if (!check_fsp_open(conn, req, fsp)) {
370 if (fsp->is_directory) {
374 if (fsp->fake_file_handle == NULL) {
378 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
382 if (fsp->fake_file_handle->private_data == NULL) {
389 /****************************************************************************
390 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
391 ****************************************************************************/
393 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
396 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
397 && (req->vuid == (fsp)->vuid)) {
401 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
405 /****************************************************************************
406 Reply to a (netbios-level) special message.
407 ****************************************************************************/
409 void reply_special(char *inbuf)
411 int msg_type = CVAL(inbuf,0);
412 int msg_flags = CVAL(inbuf,1);
417 * We only really use 4 bytes of the outbuf, but for the smb_setlen
418 * calculation & friends (srv_send_smb uses that) we need the full smb
421 char outbuf[smb_size];
425 memset(outbuf, '\0', sizeof(outbuf));
427 smb_setlen(outbuf,0);
430 case 0x81: /* session request */
432 if (already_got_session) {
433 exit_server_cleanly("multiple session request not permitted");
436 SCVAL(outbuf,0,0x82);
438 if (name_len(inbuf+4) > 50 ||
439 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
440 DEBUG(0,("Invalid name length in session request\n"));
443 name_extract(inbuf,4,name1);
444 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
445 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
448 set_local_machine_name(name1, True);
449 set_remote_machine_name(name2, True);
451 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
452 get_local_machine_name(), get_remote_machine_name(),
455 if (name_type == 'R') {
456 /* We are being asked for a pathworks session ---
458 SCVAL(outbuf, 0,0x83);
462 /* only add the client's machine name to the list
463 of possibly valid usernames if we are operating
464 in share mode security */
465 if (lp_security() == SEC_SHARE) {
466 add_session_user(get_remote_machine_name());
469 reload_services(True);
472 already_got_session = True;
475 case 0x89: /* session keepalive request
476 (some old clients produce this?) */
477 SCVAL(outbuf,0,SMBkeepalive);
481 case 0x82: /* positive session response */
482 case 0x83: /* negative session response */
483 case 0x84: /* retarget session response */
484 DEBUG(0,("Unexpected session response\n"));
487 case SMBkeepalive: /* session keepalive */
492 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
493 msg_type, msg_flags));
495 srv_send_smb(smbd_server_fd(), outbuf, false, NULL);
499 /****************************************************************************
501 conn POINTER CAN BE NULL HERE !
502 ****************************************************************************/
504 void reply_tcon(struct smb_request *req)
506 connection_struct *conn = req->conn;
508 char *service_buf = NULL;
509 char *password = NULL;
514 DATA_BLOB password_blob;
515 TALLOC_CTX *ctx = talloc_tos();
517 START_PROFILE(SMBtcon);
519 if (req->buflen < 4) {
520 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
521 END_PROFILE(SMBtcon);
525 p = (const char *)req->buf + 1;
526 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
528 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
530 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
533 if (service_buf == NULL || password == NULL || dev == NULL) {
534 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
535 END_PROFILE(SMBtcon);
538 p = strrchr_m(service_buf,'\\');
542 service = service_buf;
545 password_blob = data_blob(password, pwlen+1);
547 conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
550 data_blob_clear_free(&password_blob);
553 reply_nterror(req, nt_status);
554 END_PROFILE(SMBtcon);
558 reply_outbuf(req, 2, 0);
559 SSVAL(req->outbuf,smb_vwv0,max_recv);
560 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
561 SSVAL(req->outbuf,smb_tid,conn->cnum);
563 DEBUG(3,("tcon service=%s cnum=%d\n",
564 service, conn->cnum));
566 END_PROFILE(SMBtcon);
570 /****************************************************************************
571 Reply to a tcon and X.
572 conn POINTER CAN BE NULL HERE !
573 ****************************************************************************/
575 void reply_tcon_and_X(struct smb_request *req)
577 connection_struct *conn = req->conn;
578 const char *service = NULL;
580 TALLOC_CTX *ctx = talloc_tos();
581 /* what the cleint thinks the device is */
582 char *client_devicetype = NULL;
583 /* what the server tells the client the share represents */
584 const char *server_devicetype;
591 START_PROFILE(SMBtconX);
594 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
595 END_PROFILE(SMBtconX);
599 passlen = SVAL(req->vwv+3, 0);
600 tcon_flags = SVAL(req->vwv+2, 0);
602 /* we might have to close an old one */
603 if ((tcon_flags & 0x1) && conn) {
604 close_cnum(conn,req->vuid);
609 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
610 reply_doserror(req, ERRDOS, ERRbuftoosmall);
611 END_PROFILE(SMBtconX);
615 if (global_encrypted_passwords_negotiated) {
616 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
617 if (lp_security() == SEC_SHARE) {
619 * Security = share always has a pad byte
620 * after the password.
622 p = (const char *)req->buf + passlen + 1;
624 p = (const char *)req->buf + passlen;
627 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
628 /* Ensure correct termination */
629 password.data[passlen]=0;
630 p = (const char *)req->buf + passlen + 1;
633 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
636 data_blob_clear_free(&password);
637 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
638 END_PROFILE(SMBtconX);
643 * the service name can be either: \\server\share
644 * or share directly like on the DELL PowerVault 705
647 q = strchr_m(path+2,'\\');
649 data_blob_clear_free(&password);
650 reply_doserror(req, ERRDOS, ERRnosuchshare);
651 END_PROFILE(SMBtconX);
659 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
660 &client_devicetype, p,
661 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
663 if (client_devicetype == NULL) {
664 data_blob_clear_free(&password);
665 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
666 END_PROFILE(SMBtconX);
670 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
672 conn = make_connection(service, password, client_devicetype,
673 req->vuid, &nt_status);
676 data_blob_clear_free(&password);
679 reply_nterror(req, nt_status);
680 END_PROFILE(SMBtconX);
685 server_devicetype = "IPC";
686 else if ( IS_PRINT(conn) )
687 server_devicetype = "LPT1:";
689 server_devicetype = "A:";
691 if (Protocol < PROTOCOL_NT1) {
692 reply_outbuf(req, 2, 0);
693 if (message_push_string(&req->outbuf, server_devicetype,
694 STR_TERMINATE|STR_ASCII) == -1) {
695 reply_nterror(req, NT_STATUS_NO_MEMORY);
696 END_PROFILE(SMBtconX);
700 /* NT sets the fstype of IPC$ to the null string */
701 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
703 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
704 /* Return permissions. */
708 reply_outbuf(req, 7, 0);
711 perm1 = FILE_ALL_ACCESS;
712 perm2 = FILE_ALL_ACCESS;
714 perm1 = CAN_WRITE(conn) ?
719 SIVAL(req->outbuf, smb_vwv3, perm1);
720 SIVAL(req->outbuf, smb_vwv5, perm2);
722 reply_outbuf(req, 3, 0);
725 if ((message_push_string(&req->outbuf, server_devicetype,
726 STR_TERMINATE|STR_ASCII) == -1)
727 || (message_push_string(&req->outbuf, fstype,
728 STR_TERMINATE) == -1)) {
729 reply_nterror(req, NT_STATUS_NO_MEMORY);
730 END_PROFILE(SMBtconX);
734 /* what does setting this bit do? It is set by NT4 and
735 may affect the ability to autorun mounted cdroms */
736 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
737 (lp_csc_policy(SNUM(conn)) << 2));
739 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
740 DEBUG(2,("Serving %s as a Dfs root\n",
741 lp_servicename(SNUM(conn)) ));
742 SSVAL(req->outbuf, smb_vwv2,
743 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
748 DEBUG(3,("tconX service=%s \n",
751 /* set the incoming and outgoing tid to the just created one */
752 SSVAL(req->inbuf,smb_tid,conn->cnum);
753 SSVAL(req->outbuf,smb_tid,conn->cnum);
755 END_PROFILE(SMBtconX);
761 /****************************************************************************
762 Reply to an unknown type.
763 ****************************************************************************/
765 void reply_unknown_new(struct smb_request *req, uint8 type)
767 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
768 smb_fn_name(type), type, type));
769 reply_doserror(req, ERRSRV, ERRunknownsmb);
773 /****************************************************************************
775 conn POINTER CAN BE NULL HERE !
776 ****************************************************************************/
778 void reply_ioctl(struct smb_request *req)
780 connection_struct *conn = req->conn;
787 START_PROFILE(SMBioctl);
790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
791 END_PROFILE(SMBioctl);
795 device = SVAL(req->vwv+1, 0);
796 function = SVAL(req->vwv+2, 0);
797 ioctl_code = (device << 16) + function;
799 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
801 switch (ioctl_code) {
802 case IOCTL_QUERY_JOB_INFO:
806 reply_doserror(req, ERRSRV, ERRnosupport);
807 END_PROFILE(SMBioctl);
811 reply_outbuf(req, 8, replysize+1);
812 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
813 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
814 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
815 p = smb_buf(req->outbuf);
816 memset(p, '\0', replysize+1); /* valgrind-safe. */
817 p += 1; /* Allow for alignment */
819 switch (ioctl_code) {
820 case IOCTL_QUERY_JOB_INFO:
822 files_struct *fsp = file_fsp(
823 req, SVAL(req->vwv+0, 0));
825 reply_doserror(req, ERRDOS, ERRbadfid);
826 END_PROFILE(SMBioctl);
829 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
830 srvstr_push((char *)req->outbuf, req->flags2, p+2,
832 STR_TERMINATE|STR_ASCII);
834 srvstr_push((char *)req->outbuf, req->flags2,
835 p+18, lp_servicename(SNUM(conn)),
836 13, STR_TERMINATE|STR_ASCII);
844 END_PROFILE(SMBioctl);
848 /****************************************************************************
849 Strange checkpath NTSTATUS mapping.
850 ****************************************************************************/
852 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
854 /* Strange DOS error code semantics only for checkpath... */
855 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
856 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
857 /* We need to map to ERRbadpath */
858 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
864 /****************************************************************************
865 Reply to a checkpath.
866 ****************************************************************************/
868 void reply_checkpath(struct smb_request *req)
870 connection_struct *conn = req->conn;
872 SMB_STRUCT_STAT sbuf;
874 TALLOC_CTX *ctx = talloc_tos();
876 START_PROFILE(SMBcheckpath);
878 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
879 STR_TERMINATE, &status);
881 if (!NT_STATUS_IS_OK(status)) {
882 status = map_checkpath_error(req->flags2, status);
883 reply_nterror(req, status);
884 END_PROFILE(SMBcheckpath);
888 status = resolve_dfspath(ctx, conn,
889 req->flags2 & FLAGS2_DFS_PATHNAMES,
892 if (!NT_STATUS_IS_OK(status)) {
893 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
894 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
896 END_PROFILE(SMBcheckpath);
902 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
904 status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf);
905 if (!NT_STATUS_IS_OK(status)) {
909 status = check_name(conn, name);
910 if (!NT_STATUS_IS_OK(status)) {
911 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
915 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
916 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
917 status = map_nt_error_from_unix(errno);
921 if (!S_ISDIR(sbuf.st_mode)) {
922 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
924 END_PROFILE(SMBcheckpath);
928 reply_outbuf(req, 0, 0);
930 END_PROFILE(SMBcheckpath);
935 END_PROFILE(SMBcheckpath);
937 /* We special case this - as when a Windows machine
938 is parsing a path is steps through the components
939 one at a time - if a component fails it expects
940 ERRbadpath, not ERRbadfile.
942 status = map_checkpath_error(req->flags2, status);
943 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
945 * Windows returns different error codes if
946 * the parent directory is valid but not the
947 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
948 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
949 * if the path is invalid.
951 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
956 reply_nterror(req, status);
959 /****************************************************************************
961 ****************************************************************************/
963 void reply_getatr(struct smb_request *req)
965 connection_struct *conn = req->conn;
967 SMB_STRUCT_STAT sbuf;
973 TALLOC_CTX *ctx = talloc_tos();
975 START_PROFILE(SMBgetatr);
977 p = (const char *)req->buf + 1;
978 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
979 if (!NT_STATUS_IS_OK(status)) {
980 reply_nterror(req, status);
981 END_PROFILE(SMBgetatr);
985 status = resolve_dfspath(ctx, conn,
986 req->flags2 & FLAGS2_DFS_PATHNAMES,
989 if (!NT_STATUS_IS_OK(status)) {
990 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
991 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
993 END_PROFILE(SMBgetatr);
996 reply_nterror(req, status);
997 END_PROFILE(SMBgetatr);
1001 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1002 under WfWg - weird! */
1003 if (*fname == '\0') {
1004 mode = aHIDDEN | aDIR;
1005 if (!CAN_WRITE(conn)) {
1011 status = unix_convert(ctx, conn, fname, False, &fname, NULL,&sbuf);
1012 if (!NT_STATUS_IS_OK(status)) {
1013 reply_nterror(req, status);
1014 END_PROFILE(SMBgetatr);
1017 status = check_name(conn, fname);
1018 if (!NT_STATUS_IS_OK(status)) {
1019 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1020 reply_nterror(req, status);
1021 END_PROFILE(SMBgetatr);
1024 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
1025 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1026 reply_unixerror(req, ERRDOS,ERRbadfile);
1027 END_PROFILE(SMBgetatr);
1031 mode = dos_mode(conn,fname,&sbuf);
1032 size = sbuf.st_size;
1033 mtime = sbuf.st_mtime;
1039 reply_outbuf(req, 10, 0);
1041 SSVAL(req->outbuf,smb_vwv0,mode);
1042 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1043 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1045 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1047 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1049 if (Protocol >= PROTOCOL_NT1) {
1050 SSVAL(req->outbuf, smb_flg2,
1051 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1054 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1056 END_PROFILE(SMBgetatr);
1060 /****************************************************************************
1062 ****************************************************************************/
1064 void reply_setatr(struct smb_request *req)
1066 struct smb_file_time ft;
1067 connection_struct *conn = req->conn;
1071 SMB_STRUCT_STAT sbuf;
1074 TALLOC_CTX *ctx = talloc_tos();
1076 START_PROFILE(SMBsetatr);
1081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1085 p = (const char *)req->buf + 1;
1086 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1087 if (!NT_STATUS_IS_OK(status)) {
1088 reply_nterror(req, status);
1089 END_PROFILE(SMBsetatr);
1093 status = resolve_dfspath(ctx, conn,
1094 req->flags2 & FLAGS2_DFS_PATHNAMES,
1097 if (!NT_STATUS_IS_OK(status)) {
1098 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1099 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1100 ERRSRV, ERRbadpath);
1101 END_PROFILE(SMBsetatr);
1104 reply_nterror(req, status);
1105 END_PROFILE(SMBsetatr);
1109 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
1110 if (!NT_STATUS_IS_OK(status)) {
1111 reply_nterror(req, status);
1112 END_PROFILE(SMBsetatr);
1116 status = check_name(conn, fname);
1117 if (!NT_STATUS_IS_OK(status)) {
1118 reply_nterror(req, status);
1119 END_PROFILE(SMBsetatr);
1123 if (fname[0] == '.' && fname[1] == '\0') {
1125 * Not sure here is the right place to catch this
1126 * condition. Might be moved to somewhere else later -- vl
1128 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1129 END_PROFILE(SMBsetatr);
1133 mode = SVAL(req->vwv+0, 0);
1134 mtime = srv_make_unix_date3(req->vwv+1);
1136 ft.mtime = convert_time_t_to_timespec(mtime);
1137 status = smb_set_file_time(conn, NULL, fname,
1139 if (!NT_STATUS_IS_OK(status)) {
1140 reply_unixerror(req, ERRDOS, ERRnoaccess);
1141 END_PROFILE(SMBsetatr);
1145 if (mode != FILE_ATTRIBUTE_NORMAL) {
1146 if (VALID_STAT_OF_DIR(sbuf))
1151 if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) {
1152 reply_unixerror(req, ERRDOS, ERRnoaccess);
1153 END_PROFILE(SMBsetatr);
1158 reply_outbuf(req, 0, 0);
1160 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1162 END_PROFILE(SMBsetatr);
1166 /****************************************************************************
1168 ****************************************************************************/
1170 void reply_dskattr(struct smb_request *req)
1172 connection_struct *conn = req->conn;
1173 uint64_t dfree,dsize,bsize;
1174 START_PROFILE(SMBdskattr);
1176 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1177 reply_unixerror(req, ERRHRD, ERRgeneral);
1178 END_PROFILE(SMBdskattr);
1182 reply_outbuf(req, 5, 0);
1184 if (Protocol <= PROTOCOL_LANMAN2) {
1185 double total_space, free_space;
1186 /* we need to scale this to a number that DOS6 can handle. We
1187 use floating point so we can handle large drives on systems
1188 that don't have 64 bit integers
1190 we end up displaying a maximum of 2G to DOS systems
1192 total_space = dsize * (double)bsize;
1193 free_space = dfree * (double)bsize;
1195 dsize = (uint64_t)((total_space+63*512) / (64*512));
1196 dfree = (uint64_t)((free_space+63*512) / (64*512));
1198 if (dsize > 0xFFFF) dsize = 0xFFFF;
1199 if (dfree > 0xFFFF) dfree = 0xFFFF;
1201 SSVAL(req->outbuf,smb_vwv0,dsize);
1202 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1203 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1204 SSVAL(req->outbuf,smb_vwv3,dfree);
1206 SSVAL(req->outbuf,smb_vwv0,dsize);
1207 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1208 SSVAL(req->outbuf,smb_vwv2,512);
1209 SSVAL(req->outbuf,smb_vwv3,dfree);
1212 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1214 END_PROFILE(SMBdskattr);
1218 /****************************************************************************
1220 Can be called from SMBsearch, SMBffirst or SMBfunique.
1221 ****************************************************************************/
1223 void reply_search(struct smb_request *req)
1225 connection_struct *conn = req->conn;
1226 const char *mask = NULL;
1227 char *directory = NULL;
1233 unsigned int numentries = 0;
1234 unsigned int maxentries = 0;
1235 bool finished = False;
1241 bool check_descend = False;
1242 bool expect_close = False;
1244 bool mask_contains_wcard = False;
1245 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1246 TALLOC_CTX *ctx = talloc_tos();
1247 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1249 START_PROFILE(SMBsearch);
1252 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1253 END_PROFILE(SMBsearch);
1257 if (lp_posix_pathnames()) {
1258 reply_unknown_new(req, req->cmd);
1259 END_PROFILE(SMBsearch);
1263 /* If we were called as SMBffirst then we must expect close. */
1264 if(req->cmd == SMBffirst) {
1265 expect_close = True;
1268 reply_outbuf(req, 1, 3);
1269 maxentries = SVAL(req->vwv+0, 0);
1270 dirtype = SVAL(req->vwv+1, 0);
1271 p = (const char *)req->buf + 1;
1272 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1273 &nt_status, &mask_contains_wcard);
1274 if (!NT_STATUS_IS_OK(nt_status)) {
1275 reply_nterror(req, nt_status);
1276 END_PROFILE(SMBsearch);
1280 nt_status = resolve_dfspath_wcard(ctx, conn,
1281 req->flags2 & FLAGS2_DFS_PATHNAMES,
1284 &mask_contains_wcard);
1285 if (!NT_STATUS_IS_OK(nt_status)) {
1286 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1287 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1288 ERRSRV, ERRbadpath);
1289 END_PROFILE(SMBsearch);
1292 reply_nterror(req, nt_status);
1293 END_PROFILE(SMBsearch);
1298 status_len = SVAL(p, 0);
1301 /* dirtype &= ~aDIR; */
1303 if (status_len == 0) {
1304 SMB_STRUCT_STAT sbuf;
1306 nt_status = unix_convert(ctx, conn, path, True,
1307 &directory, NULL, &sbuf);
1308 if (!NT_STATUS_IS_OK(nt_status)) {
1309 reply_nterror(req, nt_status);
1310 END_PROFILE(SMBsearch);
1314 nt_status = check_name(conn, directory);
1315 if (!NT_STATUS_IS_OK(nt_status)) {
1316 reply_nterror(req, nt_status);
1317 END_PROFILE(SMBsearch);
1321 p = strrchr_m(directory,'/');
1322 if ((p != NULL) && (*directory != '/')) {
1324 directory = talloc_strndup(ctx, directory,
1325 PTR_DIFF(p, directory));
1328 directory = talloc_strdup(ctx,".");
1332 reply_nterror(req, NT_STATUS_NO_MEMORY);
1333 END_PROFILE(SMBsearch);
1337 memset((char *)status,'\0',21);
1338 SCVAL(status,0,(dirtype & 0x1F));
1340 nt_status = dptr_create(conn,
1346 mask_contains_wcard,
1349 if (!NT_STATUS_IS_OK(nt_status)) {
1350 reply_nterror(req, nt_status);
1351 END_PROFILE(SMBsearch);
1354 dptr_num = dptr_dnum(conn->dirptr);
1358 memcpy(status,p,21);
1359 status_dirtype = CVAL(status,0) & 0x1F;
1360 if (status_dirtype != (dirtype & 0x1F)) {
1361 dirtype = status_dirtype;
1364 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1365 if (!conn->dirptr) {
1368 string_set(&conn->dirpath,dptr_path(dptr_num));
1369 mask = dptr_wcard(dptr_num);
1374 * For a 'continue' search we have no string. So
1375 * check from the initial saved string.
1377 mask_contains_wcard = ms_has_wild(mask);
1378 dirtype = dptr_attr(dptr_num);
1381 DEBUG(4,("dptr_num is %d\n",dptr_num));
1383 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1384 dptr_init_search_op(conn->dirptr);
1386 if ((dirtype&0x1F) == aVOLID) {
1387 char buf[DIR_STRUCT_SIZE];
1388 memcpy(buf,status,21);
1389 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1390 0,aVOLID,0,!allow_long_path_components)) {
1391 reply_nterror(req, NT_STATUS_NO_MEMORY);
1392 END_PROFILE(SMBsearch);
1395 dptr_fill(buf+12,dptr_num);
1396 if (dptr_zero(buf+12) && (status_len==0)) {
1401 if (message_push_blob(&req->outbuf,
1402 data_blob_const(buf, sizeof(buf)))
1404 reply_nterror(req, NT_STATUS_NO_MEMORY);
1405 END_PROFILE(SMBsearch);
1413 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1416 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1417 conn->dirpath,lp_dontdescend(SNUM(conn))));
1418 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1419 check_descend = True;
1422 for (i=numentries;(i<maxentries) && !finished;i++) {
1423 finished = !get_dir_entry(ctx,
1434 char buf[DIR_STRUCT_SIZE];
1435 memcpy(buf,status,21);
1436 if (!make_dir_struct(ctx,
1443 !allow_long_path_components)) {
1444 reply_nterror(req, NT_STATUS_NO_MEMORY);
1445 END_PROFILE(SMBsearch);
1448 if (!dptr_fill(buf+12,dptr_num)) {
1451 if (message_push_blob(&req->outbuf,
1452 data_blob_const(buf, sizeof(buf)))
1454 reply_nterror(req, NT_STATUS_NO_MEMORY);
1455 END_PROFILE(SMBsearch);
1465 /* If we were called as SMBffirst with smb_search_id == NULL
1466 and no entries were found then return error and close dirptr
1469 if (numentries == 0) {
1470 dptr_close(&dptr_num);
1471 } else if(expect_close && status_len == 0) {
1472 /* Close the dptr - we know it's gone */
1473 dptr_close(&dptr_num);
1476 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1477 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1478 dptr_close(&dptr_num);
1481 if ((numentries == 0) && !mask_contains_wcard) {
1482 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1483 END_PROFILE(SMBsearch);
1487 SSVAL(req->outbuf,smb_vwv0,numentries);
1488 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1489 SCVAL(smb_buf(req->outbuf),0,5);
1490 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1492 /* The replies here are never long name. */
1493 SSVAL(req->outbuf, smb_flg2,
1494 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1495 if (!allow_long_path_components) {
1496 SSVAL(req->outbuf, smb_flg2,
1497 SVAL(req->outbuf, smb_flg2)
1498 & (~FLAGS2_LONG_PATH_COMPONENTS));
1501 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1502 SSVAL(req->outbuf, smb_flg2,
1503 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1506 directory = dptr_path(dptr_num);
1509 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1510 smb_fn_name(req->cmd),
1512 directory ? directory : "./",
1517 END_PROFILE(SMBsearch);
1521 /****************************************************************************
1522 Reply to a fclose (stop directory search).
1523 ****************************************************************************/
1525 void reply_fclose(struct smb_request *req)
1533 bool path_contains_wcard = False;
1534 TALLOC_CTX *ctx = talloc_tos();
1536 START_PROFILE(SMBfclose);
1538 if (lp_posix_pathnames()) {
1539 reply_unknown_new(req, req->cmd);
1540 END_PROFILE(SMBfclose);
1544 p = (const char *)req->buf + 1;
1545 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1546 &err, &path_contains_wcard);
1547 if (!NT_STATUS_IS_OK(err)) {
1548 reply_nterror(req, err);
1549 END_PROFILE(SMBfclose);
1553 status_len = SVAL(p,0);
1556 if (status_len == 0) {
1557 reply_doserror(req, ERRSRV, ERRsrverror);
1558 END_PROFILE(SMBfclose);
1562 memcpy(status,p,21);
1564 if(dptr_fetch(status+12,&dptr_num)) {
1565 /* Close the dptr - we know it's gone */
1566 dptr_close(&dptr_num);
1569 reply_outbuf(req, 1, 0);
1570 SSVAL(req->outbuf,smb_vwv0,0);
1572 DEBUG(3,("search close\n"));
1574 END_PROFILE(SMBfclose);
1578 /****************************************************************************
1580 ****************************************************************************/
1582 void reply_open(struct smb_request *req)
1584 connection_struct *conn = req->conn;
1590 SMB_STRUCT_STAT sbuf;
1597 uint32 create_disposition;
1598 uint32 create_options = 0;
1600 TALLOC_CTX *ctx = talloc_tos();
1602 START_PROFILE(SMBopen);
1605 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1606 END_PROFILE(SMBopen);
1610 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1611 deny_mode = SVAL(req->vwv+0, 0);
1612 dos_attr = SVAL(req->vwv+1, 0);
1614 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1615 STR_TERMINATE, &status);
1616 if (!NT_STATUS_IS_OK(status)) {
1617 reply_nterror(req, status);
1618 END_PROFILE(SMBopen);
1622 if (!map_open_params_to_ntcreate(
1623 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1624 &share_mode, &create_disposition, &create_options)) {
1625 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1626 END_PROFILE(SMBopen);
1630 status = SMB_VFS_CREATE_FILE(
1633 0, /* root_dir_fid */
1635 CFF_DOS_PATH, /* create_file_flags */
1636 access_mask, /* access_mask */
1637 share_mode, /* share_access */
1638 create_disposition, /* create_disposition*/
1639 create_options, /* create_options */
1640 dos_attr, /* file_attributes */
1641 oplock_request, /* oplock_request */
1642 0, /* allocation_size */
1649 if (!NT_STATUS_IS_OK(status)) {
1650 if (open_was_deferred(req->mid)) {
1651 /* We have re-scheduled this call. */
1652 END_PROFILE(SMBopen);
1655 reply_openerror(req, status);
1656 END_PROFILE(SMBopen);
1660 size = sbuf.st_size;
1661 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1662 mtime = sbuf.st_mtime;
1665 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1666 close_file(req, fsp, ERROR_CLOSE);
1667 reply_doserror(req, ERRDOS,ERRnoaccess);
1668 END_PROFILE(SMBopen);
1672 reply_outbuf(req, 7, 0);
1673 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1674 SSVAL(req->outbuf,smb_vwv1,fattr);
1675 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1676 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1678 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1680 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1681 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1683 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1684 SCVAL(req->outbuf,smb_flg,
1685 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1688 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1689 SCVAL(req->outbuf,smb_flg,
1690 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1692 END_PROFILE(SMBopen);
1696 /****************************************************************************
1697 Reply to an open and X.
1698 ****************************************************************************/
1700 void reply_open_and_X(struct smb_request *req)
1702 connection_struct *conn = req->conn;
1707 /* Breakout the oplock request bits so we can set the
1708 reply bits separately. */
1709 int ex_oplock_request;
1710 int core_oplock_request;
1713 int smb_sattr = SVAL(req->vwv+4, 0);
1714 uint32 smb_time = make_unix_date3(req->vwv+6);
1719 SMB_STRUCT_STAT sbuf;
1723 uint64_t allocation_size;
1724 ssize_t retval = -1;
1727 uint32 create_disposition;
1728 uint32 create_options = 0;
1729 TALLOC_CTX *ctx = talloc_tos();
1731 START_PROFILE(SMBopenX);
1733 if (req->wct < 15) {
1734 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1735 END_PROFILE(SMBopenX);
1739 open_flags = SVAL(req->vwv+2, 0);
1740 deny_mode = SVAL(req->vwv+3, 0);
1741 smb_attr = SVAL(req->vwv+5, 0);
1742 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1743 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1744 oplock_request = ex_oplock_request | core_oplock_request;
1745 smb_ofun = SVAL(req->vwv+8, 0);
1746 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1748 /* If it's an IPC, pass off the pipe handler. */
1750 if (lp_nt_pipe_support()) {
1751 reply_open_pipe_and_X(conn, req);
1753 reply_doserror(req, ERRSRV, ERRaccess);
1755 END_PROFILE(SMBopenX);
1759 /* XXXX we need to handle passed times, sattr and flags */
1760 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1761 STR_TERMINATE, &status);
1762 if (!NT_STATUS_IS_OK(status)) {
1763 reply_nterror(req, status);
1764 END_PROFILE(SMBopenX);
1768 if (!map_open_params_to_ntcreate(
1769 fname, deny_mode, smb_ofun, &access_mask,
1770 &share_mode, &create_disposition, &create_options)) {
1771 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1772 END_PROFILE(SMBopenX);
1776 status = SMB_VFS_CREATE_FILE(
1779 0, /* root_dir_fid */
1781 CFF_DOS_PATH, /* create_file_flags */
1782 access_mask, /* access_mask */
1783 share_mode, /* share_access */
1784 create_disposition, /* create_disposition*/
1785 create_options, /* create_options */
1786 smb_attr, /* file_attributes */
1787 oplock_request, /* oplock_request */
1788 0, /* allocation_size */
1792 &smb_action, /* pinfo */
1795 if (!NT_STATUS_IS_OK(status)) {
1796 END_PROFILE(SMBopenX);
1797 if (open_was_deferred(req->mid)) {
1798 /* We have re-scheduled this call. */
1801 reply_openerror(req, status);
1805 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1806 if the file is truncated or created. */
1807 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1808 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1809 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1810 close_file(req, fsp, ERROR_CLOSE);
1811 reply_nterror(req, NT_STATUS_DISK_FULL);
1812 END_PROFILE(SMBopenX);
1815 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1817 close_file(req, fsp, ERROR_CLOSE);
1818 reply_nterror(req, NT_STATUS_DISK_FULL);
1819 END_PROFILE(SMBopenX);
1822 sbuf.st_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
1825 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1826 mtime = sbuf.st_mtime;
1828 close_file(req, fsp, ERROR_CLOSE);
1829 reply_doserror(req, ERRDOS, ERRnoaccess);
1830 END_PROFILE(SMBopenX);
1834 /* If the caller set the extended oplock request bit
1835 and we granted one (by whatever means) - set the
1836 correct bit for extended oplock reply.
1839 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1840 smb_action |= EXTENDED_OPLOCK_GRANTED;
1843 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1844 smb_action |= EXTENDED_OPLOCK_GRANTED;
1847 /* If the caller set the core oplock request bit
1848 and we granted one (by whatever means) - set the
1849 correct bit for core oplock reply.
1852 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1853 reply_outbuf(req, 19, 0);
1855 reply_outbuf(req, 15, 0);
1858 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1859 SCVAL(req->outbuf, smb_flg,
1860 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1863 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1864 SCVAL(req->outbuf, smb_flg,
1865 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1868 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1869 SSVAL(req->outbuf,smb_vwv3,fattr);
1870 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1871 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1873 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1875 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1876 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1877 SSVAL(req->outbuf,smb_vwv11,smb_action);
1879 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1880 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1883 END_PROFILE(SMBopenX);
1888 /****************************************************************************
1889 Reply to a SMBulogoffX.
1890 ****************************************************************************/
1892 void reply_ulogoffX(struct smb_request *req)
1896 START_PROFILE(SMBulogoffX);
1898 vuser = get_valid_user_struct(req->vuid);
1901 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1905 /* in user level security we are supposed to close any files
1906 open by this user */
1907 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1908 file_close_user(req->vuid);
1911 invalidate_vuid(req->vuid);
1913 reply_outbuf(req, 2, 0);
1915 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1917 END_PROFILE(SMBulogoffX);
1921 /****************************************************************************
1922 Reply to a mknew or a create.
1923 ****************************************************************************/
1925 void reply_mknew(struct smb_request *req)
1927 connection_struct *conn = req->conn;
1930 struct smb_file_time ft;
1932 int oplock_request = 0;
1933 SMB_STRUCT_STAT sbuf;
1935 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1936 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1937 uint32 create_disposition;
1938 uint32 create_options = 0;
1939 TALLOC_CTX *ctx = talloc_tos();
1941 START_PROFILE(SMBcreate);
1945 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1946 END_PROFILE(SMBcreate);
1950 fattr = SVAL(req->vwv+0, 0);
1951 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1954 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
1956 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
1957 STR_TERMINATE, &status);
1958 if (!NT_STATUS_IS_OK(status)) {
1959 reply_nterror(req, status);
1960 END_PROFILE(SMBcreate);
1964 if (fattr & aVOLID) {
1965 DEBUG(0,("Attempt to create file (%s) with volid set - "
1966 "please report this\n", fname));
1969 if(req->cmd == SMBmknew) {
1970 /* We should fail if file exists. */
1971 create_disposition = FILE_CREATE;
1973 /* Create if file doesn't exist, truncate if it does. */
1974 create_disposition = FILE_OVERWRITE_IF;
1977 status = SMB_VFS_CREATE_FILE(
1980 0, /* root_dir_fid */
1982 CFF_DOS_PATH, /* create_file_flags */
1983 access_mask, /* access_mask */
1984 share_mode, /* share_access */
1985 create_disposition, /* create_disposition*/
1986 create_options, /* create_options */
1987 fattr, /* file_attributes */
1988 oplock_request, /* oplock_request */
1989 0, /* allocation_size */
1996 if (!NT_STATUS_IS_OK(status)) {
1997 END_PROFILE(SMBcreate);
1998 if (open_was_deferred(req->mid)) {
1999 /* We have re-scheduled this call. */
2002 reply_openerror(req, status);
2006 ft.atime = get_atimespec(&sbuf); /* atime. */
2007 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true);
2008 if (!NT_STATUS_IS_OK(status)) {
2009 END_PROFILE(SMBcreate);
2010 reply_openerror(req, status);
2014 reply_outbuf(req, 1, 0);
2015 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2017 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2018 SCVAL(req->outbuf,smb_flg,
2019 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2022 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2023 SCVAL(req->outbuf,smb_flg,
2024 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2027 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2028 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2029 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2031 END_PROFILE(SMBcreate);
2035 /****************************************************************************
2036 Reply to a create temporary file.
2037 ****************************************************************************/
2039 void reply_ctemp(struct smb_request *req)
2041 connection_struct *conn = req->conn;
2047 SMB_STRUCT_STAT sbuf;
2050 TALLOC_CTX *ctx = talloc_tos();
2052 START_PROFILE(SMBctemp);
2055 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2056 END_PROFILE(SMBctemp);
2060 fattr = SVAL(req->vwv+0, 0);
2061 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2063 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2064 STR_TERMINATE, &status);
2065 if (!NT_STATUS_IS_OK(status)) {
2066 reply_nterror(req, status);
2067 END_PROFILE(SMBctemp);
2071 fname = talloc_asprintf(ctx,
2075 fname = talloc_strdup(ctx, "TMXXXXXX");
2079 reply_nterror(req, NT_STATUS_NO_MEMORY);
2080 END_PROFILE(SMBctemp);
2084 status = resolve_dfspath(ctx, conn,
2085 req->flags2 & FLAGS2_DFS_PATHNAMES,
2088 if (!NT_STATUS_IS_OK(status)) {
2089 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2090 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2091 ERRSRV, ERRbadpath);
2092 END_PROFILE(SMBctemp);
2095 reply_nterror(req, status);
2096 END_PROFILE(SMBctemp);
2100 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
2101 if (!NT_STATUS_IS_OK(status)) {
2102 reply_nterror(req, status);
2103 END_PROFILE(SMBctemp);
2107 status = check_name(conn, fname);
2108 if (!NT_STATUS_IS_OK(status)) {
2109 reply_nterror(req, status);
2110 END_PROFILE(SMBctemp);
2114 tmpfd = smb_mkstemp(fname);
2116 reply_unixerror(req, ERRDOS, ERRnoaccess);
2117 END_PROFILE(SMBctemp);
2121 SMB_VFS_STAT(conn,fname,&sbuf);
2123 /* We should fail if file does not exist. */
2124 status = SMB_VFS_CREATE_FILE(
2127 0, /* root_dir_fid */
2129 0, /* create_file_flags */
2130 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2131 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2132 FILE_OPEN, /* create_disposition*/
2133 0, /* create_options */
2134 fattr, /* file_attributes */
2135 oplock_request, /* oplock_request */
2136 0, /* allocation_size */
2143 /* close fd from smb_mkstemp() */
2146 if (!NT_STATUS_IS_OK(status)) {
2147 if (open_was_deferred(req->mid)) {
2148 /* We have re-scheduled this call. */
2149 END_PROFILE(SMBctemp);
2152 reply_openerror(req, status);
2153 END_PROFILE(SMBctemp);
2157 reply_outbuf(req, 1, 0);
2158 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2160 /* the returned filename is relative to the directory */
2161 s = strrchr_m(fsp->fsp_name, '/');
2169 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2170 thing in the byte section. JRA */
2171 SSVALS(p, 0, -1); /* what is this? not in spec */
2173 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2175 reply_nterror(req, NT_STATUS_NO_MEMORY);
2176 END_PROFILE(SMBctemp);
2180 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2181 SCVAL(req->outbuf, smb_flg,
2182 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2185 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2186 SCVAL(req->outbuf, smb_flg,
2187 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2190 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2191 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2192 fsp->fh->fd, (unsigned int)sbuf.st_mode ) );
2194 END_PROFILE(SMBctemp);
2198 /*******************************************************************
2199 Check if a user is allowed to rename a file.
2200 ********************************************************************/
2202 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2203 uint16 dirtype, SMB_STRUCT_STAT *pst)
2207 if (!CAN_WRITE(conn)) {
2208 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2211 fmode = dos_mode(conn, fsp->fsp_name, pst);
2212 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2213 return NT_STATUS_NO_SUCH_FILE;
2216 if (S_ISDIR(pst->st_mode)) {
2217 if (fsp->posix_open) {
2218 return NT_STATUS_OK;
2221 /* If no pathnames are open below this
2222 directory, allow the rename. */
2224 if (file_find_subpath(fsp)) {
2225 return NT_STATUS_ACCESS_DENIED;
2227 return NT_STATUS_OK;
2230 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2231 return NT_STATUS_OK;
2234 return NT_STATUS_ACCESS_DENIED;
2237 /*******************************************************************
2238 * unlink a file with all relevant access checks
2239 *******************************************************************/
2241 static NTSTATUS do_unlink(connection_struct *conn,
2242 struct smb_request *req,
2246 SMB_STRUCT_STAT sbuf;
2249 uint32 dirtype_orig = dirtype;
2252 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2254 if (!CAN_WRITE(conn)) {
2255 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2258 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2259 return map_nt_error_from_unix(errno);
2262 fattr = dos_mode(conn,fname,&sbuf);
2264 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2265 dirtype = aDIR|aARCH|aRONLY;
2268 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2270 return NT_STATUS_NO_SUCH_FILE;
2273 if (!dir_check_ftype(conn, fattr, dirtype)) {
2275 return NT_STATUS_FILE_IS_A_DIRECTORY;
2277 return NT_STATUS_NO_SUCH_FILE;
2280 if (dirtype_orig & 0x8000) {
2281 /* These will never be set for POSIX. */
2282 return NT_STATUS_NO_SUCH_FILE;
2286 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2287 return NT_STATUS_FILE_IS_A_DIRECTORY;
2290 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2291 return NT_STATUS_NO_SUCH_FILE;
2294 if (dirtype & 0xFF00) {
2295 /* These will never be set for POSIX. */
2296 return NT_STATUS_NO_SUCH_FILE;
2301 return NT_STATUS_NO_SUCH_FILE;
2304 /* Can't delete a directory. */
2306 return NT_STATUS_FILE_IS_A_DIRECTORY;
2311 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2312 return NT_STATUS_OBJECT_NAME_INVALID;
2313 #endif /* JRATEST */
2315 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2317 On a Windows share, a file with read-only dosmode can be opened with
2318 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2319 fails with NT_STATUS_CANNOT_DELETE error.
2321 This semantic causes a problem that a user can not
2322 rename a file with read-only dosmode on a Samba share
2323 from a Windows command prompt (i.e. cmd.exe, but can rename
2324 from Windows Explorer).
2327 if (!lp_delete_readonly(SNUM(conn))) {
2328 if (fattr & aRONLY) {
2329 return NT_STATUS_CANNOT_DELETE;
2333 /* On open checks the open itself will check the share mode, so
2334 don't do it here as we'll get it wrong. */
2336 status = SMB_VFS_CREATE_FILE
2339 0, /* root_dir_fid */
2341 0, /* create_file_flags */
2342 DELETE_ACCESS, /* access_mask */
2343 FILE_SHARE_NONE, /* share_access */
2344 FILE_OPEN, /* create_disposition*/
2345 FILE_NON_DIRECTORY_FILE, /* create_options */
2346 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2347 0, /* oplock_request */
2348 0, /* allocation_size */
2355 if (!NT_STATUS_IS_OK(status)) {
2356 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2357 nt_errstr(status)));
2361 /* The set is across all open files on this dev/inode pair. */
2362 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2363 close_file(req, fsp, NORMAL_CLOSE);
2364 return NT_STATUS_ACCESS_DENIED;
2367 return close_file(req, fsp, NORMAL_CLOSE);
2370 /****************************************************************************
2371 The guts of the unlink command, split out so it may be called by the NT SMB
2373 ****************************************************************************/
2375 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2376 uint32 dirtype, const char *name_in, bool has_wild)
2378 const char *directory = NULL;
2383 NTSTATUS status = NT_STATUS_OK;
2384 SMB_STRUCT_STAT sbuf, st;
2385 TALLOC_CTX *ctx = talloc_tos();
2387 status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
2388 if (!NT_STATUS_IS_OK(status)) {
2392 p = strrchr_m(name,'/');
2394 directory = talloc_strdup(ctx, ".");
2396 return NT_STATUS_NO_MEMORY;
2406 * We should only check the mangled cache
2407 * here if unix_convert failed. This means
2408 * that the path in 'mask' doesn't exist
2409 * on the file system and so we need to look
2410 * for a possible mangle. This patch from
2411 * Tine Smukavec <valentin.smukavec@hermes.si>.
2414 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
2415 char *new_mask = NULL;
2416 mangle_lookup_name_from_8_3(ctx,
2426 directory = talloc_asprintf(ctx,
2431 return NT_STATUS_NO_MEMORY;
2434 dirtype = FILE_ATTRIBUTE_NORMAL;
2437 status = check_name(conn, directory);
2438 if (!NT_STATUS_IS_OK(status)) {
2442 status = do_unlink(conn, req, directory, dirtype);
2443 if (!NT_STATUS_IS_OK(status)) {
2449 struct smb_Dir *dir_hnd = NULL;
2453 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2454 return NT_STATUS_OBJECT_NAME_INVALID;
2457 if (strequal(mask,"????????.???")) {
2462 status = check_name(conn, directory);
2463 if (!NT_STATUS_IS_OK(status)) {
2467 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2469 if (dir_hnd == NULL) {
2470 return map_nt_error_from_unix(errno);
2473 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2474 the pattern matches against the long name, otherwise the short name
2475 We don't implement this yet XXXX
2478 status = NT_STATUS_NO_SUCH_FILE;
2480 while ((dname = ReadDirName(dir_hnd, &offset, &st))) {
2483 if (!is_visible_file(conn, directory, dname, &st,
2489 /* Quick check for "." and ".." */
2490 if (ISDOT(dname) || ISDOTDOT(dname)) {
2494 if(!mask_match(dname, mask, conn->case_sensitive)) {
2498 fname = talloc_asprintf(ctx, "%s/%s",
2502 return NT_STATUS_NO_MEMORY;
2505 status = check_name(conn, fname);
2506 if (!NT_STATUS_IS_OK(status)) {
2507 TALLOC_FREE(dir_hnd);
2511 status = do_unlink(conn, req, fname, dirtype);
2512 if (!NT_STATUS_IS_OK(status)) {
2518 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2523 TALLOC_FREE(dir_hnd);
2526 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2527 status = map_nt_error_from_unix(errno);
2533 /****************************************************************************
2535 ****************************************************************************/
2537 void reply_unlink(struct smb_request *req)
2539 connection_struct *conn = req->conn;
2543 bool path_contains_wcard = False;
2544 TALLOC_CTX *ctx = talloc_tos();
2546 START_PROFILE(SMBunlink);
2549 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2550 END_PROFILE(SMBunlink);
2554 dirtype = SVAL(req->vwv+0, 0);
2556 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2557 STR_TERMINATE, &status,
2558 &path_contains_wcard);
2559 if (!NT_STATUS_IS_OK(status)) {
2560 reply_nterror(req, status);
2561 END_PROFILE(SMBunlink);
2565 status = resolve_dfspath_wcard(ctx, conn,
2566 req->flags2 & FLAGS2_DFS_PATHNAMES,
2569 &path_contains_wcard);
2570 if (!NT_STATUS_IS_OK(status)) {
2571 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2572 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2573 ERRSRV, ERRbadpath);
2574 END_PROFILE(SMBunlink);
2577 reply_nterror(req, status);
2578 END_PROFILE(SMBunlink);
2582 DEBUG(3,("reply_unlink : %s\n",name));
2584 status = unlink_internals(conn, req, dirtype, name,
2585 path_contains_wcard);
2586 if (!NT_STATUS_IS_OK(status)) {
2587 if (open_was_deferred(req->mid)) {
2588 /* We have re-scheduled this call. */
2589 END_PROFILE(SMBunlink);
2592 reply_nterror(req, status);
2593 END_PROFILE(SMBunlink);
2597 reply_outbuf(req, 0, 0);
2598 END_PROFILE(SMBunlink);
2603 /****************************************************************************
2605 ****************************************************************************/
2607 static void fail_readraw(void)
2609 const char *errstr = talloc_asprintf(talloc_tos(),
2610 "FAIL ! reply_readbraw: socket write fail (%s)",
2615 exit_server_cleanly(errstr);
2618 /****************************************************************************
2619 Fake (read/write) sendfile. Returns -1 on read or write fail.
2620 ****************************************************************************/
2622 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2626 size_t tosend = nread;
2633 bufsize = MIN(nread, 65536);
2635 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2639 while (tosend > 0) {
2643 if (tosend > bufsize) {
2648 ret = read_file(fsp,buf,startpos,cur_read);
2654 /* If we had a short read, fill with zeros. */
2655 if (ret < cur_read) {
2656 memset(buf, '\0', cur_read - ret);
2659 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2664 startpos += cur_read;
2668 return (ssize_t)nread;
2671 /****************************************************************************
2672 Deal with the case of sendfile reading less bytes from the file than
2673 requested. Fill with zeros (all we can do).
2674 ****************************************************************************/
2676 static void sendfile_short_send(files_struct *fsp,
2681 if (nread < headersize) {
2682 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2683 "header for file %s (%s). Terminating\n",
2684 fsp->fsp_name, strerror(errno) ));
2685 exit_server_cleanly("sendfile_short_send failed");
2688 nread -= headersize;
2690 if (nread < smb_maxcnt) {
2691 char *buf = SMB_CALLOC_ARRAY(char, 1024);
2693 exit_server_cleanly("sendfile_short_send: "
2697 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2698 "with zeros !\n", fsp->fsp_name));
2700 while (nread < smb_maxcnt) {
2702 * We asked for the real file size and told sendfile
2703 * to not go beyond the end of the file. But it can
2704 * happen that in between our fstat call and the
2705 * sendfile call the file was truncated. This is very
2706 * bad because we have already announced the larger
2707 * number of bytes to the client.
2709 * The best we can do now is to send 0-bytes, just as
2710 * a read from a hole in a sparse file would do.
2712 * This should happen rarely enough that I don't care
2713 * about efficiency here :-)
2717 to_write = MIN(sizeof(buf), smb_maxcnt - nread);
2718 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2719 exit_server_cleanly("sendfile_short_send: "
2720 "write_data failed");
2728 /****************************************************************************
2729 Return a readbraw error (4 bytes of zero).
2730 ****************************************************************************/
2732 static void reply_readbraw_error(void)
2736 if (write_data(smbd_server_fd(),header,4) != 4) {
2741 /****************************************************************************
2742 Use sendfile in readbraw.
2743 ****************************************************************************/
2745 static void send_file_readbraw(connection_struct *conn,
2746 struct smb_request *req,
2752 char *outbuf = NULL;
2755 #if defined(WITH_SENDFILE)
2757 * We can only use sendfile on a non-chained packet
2758 * but we can use on a non-oplocked file. tridge proved this
2759 * on a train in Germany :-). JRA.
2760 * reply_readbraw has already checked the length.
2763 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2764 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2765 ssize_t sendfile_read = -1;
2767 DATA_BLOB header_blob;
2769 _smb_setlen(header,nread);
2770 header_blob = data_blob_const(header, 4);
2772 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2773 &header_blob, startpos, nread)) == -1) {
2774 /* Returning ENOSYS means no data at all was sent.
2775 * Do this as a normal read. */
2776 if (errno == ENOSYS) {
2777 goto normal_readbraw;
2781 * Special hack for broken Linux with no working sendfile. If we
2782 * return EINTR we sent the header but not the rest of the data.
2783 * Fake this up by doing read/write calls.
2785 if (errno == EINTR) {
2786 /* Ensure we don't do this again. */
2787 set_use_sendfile(SNUM(conn), False);
2788 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2790 if (fake_sendfile(fsp, startpos, nread) == -1) {
2791 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2792 fsp->fsp_name, strerror(errno) ));
2793 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2798 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2799 fsp->fsp_name, strerror(errno) ));
2800 exit_server_cleanly("send_file_readbraw sendfile failed");
2801 } else if (sendfile_read == 0) {
2803 * Some sendfile implementations return 0 to indicate
2804 * that there was a short read, but nothing was
2805 * actually written to the socket. In this case,
2806 * fallback to the normal read path so the header gets
2807 * the correct byte count.
2809 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2810 "bytes falling back to the normal read: "
2811 "%s\n", fsp->fsp_name));
2812 goto normal_readbraw;
2815 /* Deal with possible short send. */
2816 if (sendfile_read != 4+nread) {
2817 sendfile_short_send(fsp, sendfile_read, 4, nread);
2825 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2827 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2828 (unsigned)(nread+4)));
2829 reply_readbraw_error();
2834 ret = read_file(fsp,outbuf+4,startpos,nread);
2835 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2844 _smb_setlen(outbuf,ret);
2845 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2848 TALLOC_FREE(outbuf);
2851 /****************************************************************************
2852 Reply to a readbraw (core+ protocol).
2853 ****************************************************************************/
2855 void reply_readbraw(struct smb_request *req)
2857 connection_struct *conn = req->conn;
2858 ssize_t maxcount,mincount;
2862 struct lock_struct lock;
2866 START_PROFILE(SMBreadbraw);
2868 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
2869 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2870 "raw reads/writes are disallowed.");
2874 reply_readbraw_error();
2875 END_PROFILE(SMBreadbraw);
2880 * Special check if an oplock break has been issued
2881 * and the readraw request croses on the wire, we must
2882 * return a zero length response here.
2885 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2888 * We have to do a check_fsp by hand here, as
2889 * we must always return 4 zero bytes on error,
2893 if (!fsp || !conn || conn != fsp->conn ||
2894 req->vuid != fsp->vuid ||
2895 fsp->is_directory || fsp->fh->fd == -1) {
2897 * fsp could be NULL here so use the value from the packet. JRA.
2899 DEBUG(3,("reply_readbraw: fnum %d not valid "
2901 (int)SVAL(req->vwv+0, 0)));
2902 reply_readbraw_error();
2903 END_PROFILE(SMBreadbraw);
2907 /* Do a "by hand" version of CHECK_READ. */
2908 if (!(fsp->can_read ||
2909 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2910 (fsp->access_mask & FILE_EXECUTE)))) {
2911 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2912 (int)SVAL(req->vwv+0, 0)));
2913 reply_readbraw_error();
2914 END_PROFILE(SMBreadbraw);
2918 flush_write_cache(fsp, READRAW_FLUSH);
2920 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
2921 if(req->wct == 10) {
2923 * This is a large offset (64 bit) read.
2925 #ifdef LARGE_SMB_OFF_T
2927 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
2929 #else /* !LARGE_SMB_OFF_T */
2932 * Ensure we haven't been sent a >32 bit offset.
2935 if(IVAL(req->vwv+8, 0) != 0) {
2936 DEBUG(0,("reply_readbraw: large offset "
2937 "(%x << 32) used and we don't support "
2938 "64 bit offsets.\n",
2939 (unsigned int)IVAL(req->vwv+8, 0) ));
2940 reply_readbraw_error();
2941 END_PROFILE(SMBreadbraw);
2945 #endif /* LARGE_SMB_OFF_T */
2948 DEBUG(0,("reply_readbraw: negative 64 bit "
2949 "readraw offset (%.0f) !\n",
2950 (double)startpos ));
2951 reply_readbraw_error();
2952 END_PROFILE(SMBreadbraw);
2957 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
2958 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
2960 /* ensure we don't overrun the packet size */
2961 maxcount = MIN(65535,maxcount);
2963 init_strict_lock_struct(fsp, (uint32)req->smbpid,
2964 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
2967 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
2968 reply_readbraw_error();
2969 END_PROFILE(SMBreadbraw);
2973 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
2977 if (startpos >= size) {
2980 nread = MIN(maxcount,(size - startpos));
2983 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2984 if (nread < mincount)
2988 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2989 "min=%lu nread=%lu\n",
2990 fsp->fnum, (double)startpos,
2991 (unsigned long)maxcount,
2992 (unsigned long)mincount,
2993 (unsigned long)nread ) );
2995 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
2997 DEBUG(5,("reply_readbraw finished\n"));
2999 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3001 END_PROFILE(SMBreadbraw);
3006 #define DBGC_CLASS DBGC_LOCKING
3008 /****************************************************************************
3009 Reply to a lockread (core+ protocol).
3010 ****************************************************************************/
3012 void reply_lockread(struct smb_request *req)
3014 connection_struct *conn = req->conn;
3021 struct byte_range_lock *br_lck = NULL;
3024 START_PROFILE(SMBlockread);
3027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3028 END_PROFILE(SMBlockread);
3032 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3034 if (!check_fsp(conn, req, fsp)) {
3035 END_PROFILE(SMBlockread);
3039 if (!CHECK_READ(fsp,req)) {
3040 reply_doserror(req, ERRDOS, ERRbadaccess);
3041 END_PROFILE(SMBlockread);
3045 numtoread = SVAL(req->vwv+1, 0);
3046 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3048 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3050 reply_outbuf(req, 5, numtoread + 3);
3052 data = smb_buf(req->outbuf) + 3;
3055 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3056 * protocol request that predates the read/write lock concept.
3057 * Thus instead of asking for a read lock here we need to ask
3058 * for a write lock. JRA.
3059 * Note that the requested lock size is unaffected by max_recv.
3062 br_lck = do_lock(smbd_messaging_context(),
3065 (uint64_t)numtoread,
3069 False, /* Non-blocking lock. */
3073 TALLOC_FREE(br_lck);
3075 if (NT_STATUS_V(status)) {
3076 reply_nterror(req, status);
3077 END_PROFILE(SMBlockread);
3082 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3085 if (numtoread > max_recv) {
3086 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3087 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3088 (unsigned int)numtoread, (unsigned int)max_recv ));
3089 numtoread = MIN(numtoread,max_recv);
3091 nread = read_file(fsp,data,startpos,numtoread);
3094 reply_unixerror(req, ERRDOS, ERRnoaccess);
3095 END_PROFILE(SMBlockread);
3099 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3101 SSVAL(req->outbuf,smb_vwv0,nread);
3102 SSVAL(req->outbuf,smb_vwv5,nread+3);
3103 p = smb_buf(req->outbuf);
3104 SCVAL(p,0,0); /* pad byte. */
3107 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3108 fsp->fnum, (int)numtoread, (int)nread));
3110 END_PROFILE(SMBlockread);
3115 #define DBGC_CLASS DBGC_ALL
3117 /****************************************************************************
3119 ****************************************************************************/
3121 void reply_read(struct smb_request *req)
3123 connection_struct *conn = req->conn;
3130 struct lock_struct lock;
3132 START_PROFILE(SMBread);
3135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3136 END_PROFILE(SMBread);
3140 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3142 if (!check_fsp(conn, req, fsp)) {
3143 END_PROFILE(SMBread);
3147 if (!CHECK_READ(fsp,req)) {
3148 reply_doserror(req, ERRDOS, ERRbadaccess);
3149 END_PROFILE(SMBread);
3153 numtoread = SVAL(req->vwv+1, 0);
3154 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3156 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3159 * The requested read size cannot be greater than max_recv. JRA.
3161 if (numtoread > max_recv) {
3162 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3163 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3164 (unsigned int)numtoread, (unsigned int)max_recv ));
3165 numtoread = MIN(numtoread,max_recv);
3168 reply_outbuf(req, 5, numtoread+3);
3170 data = smb_buf(req->outbuf) + 3;
3172 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3173 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3176 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3177 reply_doserror(req, ERRDOS,ERRlock);
3178 END_PROFILE(SMBread);
3183 nread = read_file(fsp,data,startpos,numtoread);
3186 reply_unixerror(req, ERRDOS,ERRnoaccess);
3190 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3192 SSVAL(req->outbuf,smb_vwv0,nread);
3193 SSVAL(req->outbuf,smb_vwv5,nread+3);
3194 SCVAL(smb_buf(req->outbuf),0,1);
3195 SSVAL(smb_buf(req->outbuf),1,nread);
3197 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",