2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
32 extern uint32 global_client_caps;
34 extern bool global_encrypted_passwords_negotiated;
36 /****************************************************************************
37 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
38 path or anything including wildcards.
39 We're assuming here that '/' is not the second byte in any multibyte char
40 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
42 ****************************************************************************/
44 /* Custom version for processing POSIX paths. */
45 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
47 static NTSTATUS check_path_syntax_internal(char *path,
49 bool *p_last_component_contains_wcard)
53 NTSTATUS ret = NT_STATUS_OK;
54 bool start_of_name_component = True;
55 bool stream_started = false;
57 *p_last_component_contains_wcard = False;
64 return NT_STATUS_OBJECT_NAME_INVALID;
67 return NT_STATUS_OBJECT_NAME_INVALID;
69 if (strchr_m(&s[1], ':')) {
70 return NT_STATUS_OBJECT_NAME_INVALID;
72 if (StrCaseCmp(s, ":$DATA") != 0) {
73 return NT_STATUS_INVALID_PARAMETER;
79 if (!stream_started && *s == ':') {
80 if (*p_last_component_contains_wcard) {
81 return NT_STATUS_OBJECT_NAME_INVALID;
83 /* stream names allow more characters than file names */
84 stream_started = true;
85 start_of_name_component = false;
89 return NT_STATUS_OBJECT_NAME_INVALID;
93 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
95 * Safe to assume is not the second part of a mb char
96 * as this is handled below.
98 /* Eat multiple '/' or '\\' */
99 while (IS_PATH_SEP(*s,posix_path)) {
102 if ((d != path) && (*s != '\0')) {
103 /* We only care about non-leading or trailing '/' or '\\' */
107 start_of_name_component = True;
109 *p_last_component_contains_wcard = False;
113 if (start_of_name_component) {
114 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
115 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
118 * No mb char starts with '.' so we're safe checking the directory separator here.
121 /* If we just added a '/' - delete it */
122 if ((d > path) && (*(d-1) == '/')) {
127 /* Are we at the start ? Can't go back further if so. */
129 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
132 /* Go back one level... */
133 /* We know this is safe as '/' cannot be part of a mb sequence. */
134 /* NOTE - if this assumption is invalid we are not in good shape... */
135 /* Decrement d first as d points to the *next* char to write into. */
136 for (d--; d > path; d--) {
140 s += 2; /* Else go past the .. */
141 /* We're still at the start of a name component, just the previous one. */
144 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
156 if (*s <= 0x1f || *s == '|') {
157 return NT_STATUS_OBJECT_NAME_INVALID;
165 *p_last_component_contains_wcard = True;
174 /* Get the size of the next MB character. */
175 next_codepoint(s,&siz);
193 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
195 return NT_STATUS_INVALID_PARAMETER;
198 start_of_name_component = False;
206 /****************************************************************************
207 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
208 No wildcards allowed.
209 ****************************************************************************/
211 NTSTATUS check_path_syntax(char *path)
214 return check_path_syntax_internal(path, False, &ignore);
217 /****************************************************************************
218 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
219 Wildcards allowed - p_contains_wcard returns true if the last component contained
221 ****************************************************************************/
223 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
225 return check_path_syntax_internal(path, False, p_contains_wcard);
228 /****************************************************************************
229 Check the path for a POSIX client.
230 We're assuming here that '/' is not the second byte in any multibyte char
231 set (a safe assumption).
232 ****************************************************************************/
234 NTSTATUS check_path_syntax_posix(char *path)
237 return check_path_syntax_internal(path, True, &ignore);
240 /****************************************************************************
241 Pull a string and check the path allowing a wilcard - provide for error return.
242 ****************************************************************************/
244 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
245 const char *base_ptr,
252 bool *contains_wcard)
258 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
262 *err = NT_STATUS_INVALID_PARAMETER;
266 *contains_wcard = False;
268 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
270 * For a DFS path the function parse_dfs_path()
271 * will do the path processing, just make a copy.
277 if (lp_posix_pathnames()) {
278 *err = check_path_syntax_posix(*pp_dest);
280 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
286 /****************************************************************************
287 Pull a string and check the path - provide for error return.
288 ****************************************************************************/
290 size_t srvstr_get_path(TALLOC_CTX *ctx,
291 const char *base_ptr,
300 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
301 src_len, flags, err, &ignore);
304 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
305 char **pp_dest, const char *src, int flags,
306 NTSTATUS *err, bool *contains_wcard)
308 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
309 pp_dest, src, smbreq_bufrem(req, src),
310 flags, err, contains_wcard);
313 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
314 char **pp_dest, const char *src, int flags,
318 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
319 flags, err, &ignore);
322 /****************************************************************************
323 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
324 ****************************************************************************/
326 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
329 if (!(fsp) || !(conn)) {
330 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
333 if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
334 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
340 /****************************************************************************
341 Check if we have a correct fsp pointing to a file.
342 ****************************************************************************/
344 bool check_fsp(connection_struct *conn, struct smb_request *req,
347 if (!check_fsp_open(conn, req, fsp)) {
350 if ((fsp)->is_directory) {
351 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
354 if ((fsp)->fh->fd == -1) {
355 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
358 (fsp)->num_smb_operations++;
362 /****************************************************************************
363 Check if we have a correct fsp pointing to a quota fake file. Replacement for
364 the CHECK_NTQUOTA_HANDLE_OK macro.
365 ****************************************************************************/
367 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
370 if (!check_fsp_open(conn, req, fsp)) {
374 if (fsp->is_directory) {
378 if (fsp->fake_file_handle == NULL) {
382 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
386 if (fsp->fake_file_handle->private_data == NULL) {
393 /****************************************************************************
394 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
395 ****************************************************************************/
397 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
400 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
401 && (req->vuid == (fsp)->vuid)) {
405 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
409 /****************************************************************************
410 Reply to a (netbios-level) special message.
411 ****************************************************************************/
413 void reply_special(char *inbuf)
415 int msg_type = CVAL(inbuf,0);
416 int msg_flags = CVAL(inbuf,1);
421 * We only really use 4 bytes of the outbuf, but for the smb_setlen
422 * calculation & friends (srv_send_smb uses that) we need the full smb
425 char outbuf[smb_size];
427 static bool already_got_session = False;
431 memset(outbuf, '\0', sizeof(outbuf));
433 smb_setlen(outbuf,0);
436 case 0x81: /* session request */
438 if (already_got_session) {
439 exit_server_cleanly("multiple session request not permitted");
442 SCVAL(outbuf,0,0x82);
444 if (name_len(inbuf+4) > 50 ||
445 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
446 DEBUG(0,("Invalid name length in session request\n"));
449 name_extract(inbuf,4,name1);
450 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
451 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
454 set_local_machine_name(name1, True);
455 set_remote_machine_name(name2, True);
457 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
458 get_local_machine_name(), get_remote_machine_name(),
461 if (name_type == 'R') {
462 /* We are being asked for a pathworks session ---
464 SCVAL(outbuf, 0,0x83);
468 /* only add the client's machine name to the list
469 of possibly valid usernames if we are operating
470 in share mode security */
471 if (lp_security() == SEC_SHARE) {
472 add_session_user(get_remote_machine_name());
475 reload_services(True);
478 already_got_session = True;
481 case 0x89: /* session keepalive request
482 (some old clients produce this?) */
483 SCVAL(outbuf,0,SMBkeepalive);
487 case 0x82: /* positive session response */
488 case 0x83: /* negative session response */
489 case 0x84: /* retarget session response */
490 DEBUG(0,("Unexpected session response\n"));
493 case SMBkeepalive: /* session keepalive */
498 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
499 msg_type, msg_flags));
501 srv_send_smb(smbd_server_fd(), outbuf, false);
505 /****************************************************************************
507 conn POINTER CAN BE NULL HERE !
508 ****************************************************************************/
510 void reply_tcon(struct smb_request *req)
512 connection_struct *conn = req->conn;
514 char *service_buf = NULL;
515 char *password = NULL;
520 DATA_BLOB password_blob;
521 TALLOC_CTX *ctx = talloc_tos();
523 START_PROFILE(SMBtcon);
525 if (req->buflen < 4) {
526 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
527 END_PROFILE(SMBtcon);
531 p = (const char *)req->buf + 1;
532 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
534 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
536 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
539 if (service_buf == NULL || password == NULL || dev == NULL) {
540 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
541 END_PROFILE(SMBtcon);
544 p = strrchr_m(service_buf,'\\');
548 service = service_buf;
551 password_blob = data_blob(password, pwlen+1);
553 conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
556 data_blob_clear_free(&password_blob);
559 reply_nterror(req, nt_status);
560 END_PROFILE(SMBtcon);
564 reply_outbuf(req, 2, 0);
565 SSVAL(req->outbuf,smb_vwv0,max_recv);
566 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
567 SSVAL(req->outbuf,smb_tid,conn->cnum);
569 DEBUG(3,("tcon service=%s cnum=%d\n",
570 service, conn->cnum));
572 END_PROFILE(SMBtcon);
576 /****************************************************************************
577 Reply to a tcon and X.
578 conn POINTER CAN BE NULL HERE !
579 ****************************************************************************/
581 void reply_tcon_and_X(struct smb_request *req)
583 connection_struct *conn = req->conn;
584 const char *service = NULL;
586 TALLOC_CTX *ctx = talloc_tos();
587 /* what the cleint thinks the device is */
588 char *client_devicetype = NULL;
589 /* what the server tells the client the share represents */
590 const char *server_devicetype;
597 START_PROFILE(SMBtconX);
600 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
601 END_PROFILE(SMBtconX);
605 passlen = SVAL(req->vwv+3, 0);
606 tcon_flags = SVAL(req->vwv+2, 0);
608 /* we might have to close an old one */
609 if ((tcon_flags & 0x1) && conn) {
610 close_cnum(conn,req->vuid);
615 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
616 reply_doserror(req, ERRDOS, ERRbuftoosmall);
617 END_PROFILE(SMBtconX);
621 if (global_encrypted_passwords_negotiated) {
622 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
623 if (lp_security() == SEC_SHARE) {
625 * Security = share always has a pad byte
626 * after the password.
628 p = (const char *)req->buf + passlen + 1;
630 p = (const char *)req->buf + passlen;
633 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
634 /* Ensure correct termination */
635 password.data[passlen]=0;
636 p = (const char *)req->buf + passlen + 1;
639 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
642 data_blob_clear_free(&password);
643 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
644 END_PROFILE(SMBtconX);
649 * the service name can be either: \\server\share
650 * or share directly like on the DELL PowerVault 705
653 q = strchr_m(path+2,'\\');
655 data_blob_clear_free(&password);
656 reply_doserror(req, ERRDOS, ERRnosuchshare);
657 END_PROFILE(SMBtconX);
665 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
666 &client_devicetype, p,
667 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
669 if (client_devicetype == NULL) {
670 data_blob_clear_free(&password);
671 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
672 END_PROFILE(SMBtconX);
676 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
678 conn = make_connection(service, password, client_devicetype,
679 req->vuid, &nt_status);
682 data_blob_clear_free(&password);
685 reply_nterror(req, nt_status);
686 END_PROFILE(SMBtconX);
691 server_devicetype = "IPC";
692 else if ( IS_PRINT(conn) )
693 server_devicetype = "LPT1:";
695 server_devicetype = "A:";
697 if (Protocol < PROTOCOL_NT1) {
698 reply_outbuf(req, 2, 0);
699 if (message_push_string(&req->outbuf, server_devicetype,
700 STR_TERMINATE|STR_ASCII) == -1) {
701 reply_nterror(req, NT_STATUS_NO_MEMORY);
702 END_PROFILE(SMBtconX);
706 /* NT sets the fstype of IPC$ to the null string */
707 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
709 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
710 /* Return permissions. */
714 reply_outbuf(req, 7, 0);
717 perm1 = FILE_ALL_ACCESS;
718 perm2 = FILE_ALL_ACCESS;
720 perm1 = CAN_WRITE(conn) ?
725 SIVAL(req->outbuf, smb_vwv3, perm1);
726 SIVAL(req->outbuf, smb_vwv5, perm2);
728 reply_outbuf(req, 3, 0);
731 if ((message_push_string(&req->outbuf, server_devicetype,
732 STR_TERMINATE|STR_ASCII) == -1)
733 || (message_push_string(&req->outbuf, fstype,
734 STR_TERMINATE) == -1)) {
735 reply_nterror(req, NT_STATUS_NO_MEMORY);
736 END_PROFILE(SMBtconX);
740 /* what does setting this bit do? It is set by NT4 and
741 may affect the ability to autorun mounted cdroms */
742 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
743 (lp_csc_policy(SNUM(conn)) << 2));
745 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
746 DEBUG(2,("Serving %s as a Dfs root\n",
747 lp_servicename(SNUM(conn)) ));
748 SSVAL(req->outbuf, smb_vwv2,
749 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
754 DEBUG(3,("tconX service=%s \n",
757 /* set the incoming and outgoing tid to the just created one */
758 SSVAL(req->inbuf,smb_tid,conn->cnum);
759 SSVAL(req->outbuf,smb_tid,conn->cnum);
761 END_PROFILE(SMBtconX);
767 /****************************************************************************
768 Reply to an unknown type.
769 ****************************************************************************/
771 void reply_unknown_new(struct smb_request *req, uint8 type)
773 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
774 smb_fn_name(type), type, type));
775 reply_doserror(req, ERRSRV, ERRunknownsmb);
779 /****************************************************************************
781 conn POINTER CAN BE NULL HERE !
782 ****************************************************************************/
784 void reply_ioctl(struct smb_request *req)
786 connection_struct *conn = req->conn;
793 START_PROFILE(SMBioctl);
796 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
797 END_PROFILE(SMBioctl);
801 device = SVAL(req->vwv+1, 0);
802 function = SVAL(req->vwv+2, 0);
803 ioctl_code = (device << 16) + function;
805 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
807 switch (ioctl_code) {
808 case IOCTL_QUERY_JOB_INFO:
812 reply_doserror(req, ERRSRV, ERRnosupport);
813 END_PROFILE(SMBioctl);
817 reply_outbuf(req, 8, replysize+1);
818 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
819 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
820 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
821 p = smb_buf(req->outbuf);
822 memset(p, '\0', replysize+1); /* valgrind-safe. */
823 p += 1; /* Allow for alignment */
825 switch (ioctl_code) {
826 case IOCTL_QUERY_JOB_INFO:
828 files_struct *fsp = file_fsp(
829 req, SVAL(req->vwv+0, 0));
831 reply_doserror(req, ERRDOS, ERRbadfid);
832 END_PROFILE(SMBioctl);
835 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
836 srvstr_push((char *)req->outbuf, req->flags2, p+2,
838 STR_TERMINATE|STR_ASCII);
840 srvstr_push((char *)req->outbuf, req->flags2,
841 p+18, lp_servicename(SNUM(conn)),
842 13, STR_TERMINATE|STR_ASCII);
850 END_PROFILE(SMBioctl);
854 /****************************************************************************
855 Strange checkpath NTSTATUS mapping.
856 ****************************************************************************/
858 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
860 /* Strange DOS error code semantics only for checkpath... */
861 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
862 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
863 /* We need to map to ERRbadpath */
864 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
870 /****************************************************************************
871 Reply to a checkpath.
872 ****************************************************************************/
874 void reply_checkpath(struct smb_request *req)
876 connection_struct *conn = req->conn;
878 SMB_STRUCT_STAT sbuf;
880 TALLOC_CTX *ctx = talloc_tos();
882 START_PROFILE(SMBcheckpath);
884 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
885 STR_TERMINATE, &status);
887 if (!NT_STATUS_IS_OK(status)) {
888 status = map_checkpath_error(req->flags2, status);
889 reply_nterror(req, status);
890 END_PROFILE(SMBcheckpath);
894 status = resolve_dfspath(ctx, conn,
895 req->flags2 & FLAGS2_DFS_PATHNAMES,
898 if (!NT_STATUS_IS_OK(status)) {
899 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
900 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
902 END_PROFILE(SMBcheckpath);
908 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
910 status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf);
911 if (!NT_STATUS_IS_OK(status)) {
915 status = check_name(conn, name);
916 if (!NT_STATUS_IS_OK(status)) {
917 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
921 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
922 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
923 status = map_nt_error_from_unix(errno);
927 if (!S_ISDIR(sbuf.st_mode)) {
928 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
930 END_PROFILE(SMBcheckpath);
934 reply_outbuf(req, 0, 0);
936 END_PROFILE(SMBcheckpath);
941 END_PROFILE(SMBcheckpath);
943 /* We special case this - as when a Windows machine
944 is parsing a path is steps through the components
945 one at a time - if a component fails it expects
946 ERRbadpath, not ERRbadfile.
948 status = map_checkpath_error(req->flags2, status);
949 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
951 * Windows returns different error codes if
952 * the parent directory is valid but not the
953 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
954 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
955 * if the path is invalid.
957 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
962 reply_nterror(req, status);
965 /****************************************************************************
967 ****************************************************************************/
969 void reply_getatr(struct smb_request *req)
971 connection_struct *conn = req->conn;
973 SMB_STRUCT_STAT sbuf;
979 TALLOC_CTX *ctx = talloc_tos();
981 START_PROFILE(SMBgetatr);
983 p = (const char *)req->buf + 1;
984 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
985 if (!NT_STATUS_IS_OK(status)) {
986 reply_nterror(req, status);
987 END_PROFILE(SMBgetatr);
991 status = resolve_dfspath(ctx, conn,
992 req->flags2 & FLAGS2_DFS_PATHNAMES,
995 if (!NT_STATUS_IS_OK(status)) {
996 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
997 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
999 END_PROFILE(SMBgetatr);
1002 reply_nterror(req, status);
1003 END_PROFILE(SMBgetatr);
1007 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1008 under WfWg - weird! */
1009 if (*fname == '\0') {
1010 mode = aHIDDEN | aDIR;
1011 if (!CAN_WRITE(conn)) {
1017 status = unix_convert(ctx, conn, fname, False, &fname, NULL,&sbuf);
1018 if (!NT_STATUS_IS_OK(status)) {
1019 reply_nterror(req, status);
1020 END_PROFILE(SMBgetatr);
1023 status = check_name(conn, fname);
1024 if (!NT_STATUS_IS_OK(status)) {
1025 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1026 reply_nterror(req, status);
1027 END_PROFILE(SMBgetatr);
1030 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
1031 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1032 reply_unixerror(req, ERRDOS,ERRbadfile);
1033 END_PROFILE(SMBgetatr);
1037 mode = dos_mode(conn,fname,&sbuf);
1038 size = sbuf.st_size;
1039 mtime = sbuf.st_mtime;
1045 reply_outbuf(req, 10, 0);
1047 SSVAL(req->outbuf,smb_vwv0,mode);
1048 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1049 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1051 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1053 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1055 if (Protocol >= PROTOCOL_NT1) {
1056 SSVAL(req->outbuf, smb_flg2,
1057 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1060 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1062 END_PROFILE(SMBgetatr);
1066 /****************************************************************************
1068 ****************************************************************************/
1070 void reply_setatr(struct smb_request *req)
1072 struct timespec ts[2];
1073 connection_struct *conn = req->conn;
1077 SMB_STRUCT_STAT sbuf;
1080 TALLOC_CTX *ctx = talloc_tos();
1082 START_PROFILE(SMBsetatr);
1087 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1091 p = (const char *)req->buf + 1;
1092 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1093 if (!NT_STATUS_IS_OK(status)) {
1094 reply_nterror(req, status);
1095 END_PROFILE(SMBsetatr);
1099 status = resolve_dfspath(ctx, conn,
1100 req->flags2 & FLAGS2_DFS_PATHNAMES,
1103 if (!NT_STATUS_IS_OK(status)) {
1104 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1105 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1106 ERRSRV, ERRbadpath);
1107 END_PROFILE(SMBsetatr);
1110 reply_nterror(req, status);
1111 END_PROFILE(SMBsetatr);
1115 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
1116 if (!NT_STATUS_IS_OK(status)) {
1117 reply_nterror(req, status);
1118 END_PROFILE(SMBsetatr);
1122 status = check_name(conn, fname);
1123 if (!NT_STATUS_IS_OK(status)) {
1124 reply_nterror(req, status);
1125 END_PROFILE(SMBsetatr);
1129 if (fname[0] == '.' && fname[1] == '\0') {
1131 * Not sure here is the right place to catch this
1132 * condition. Might be moved to somewhere else later -- vl
1134 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1135 END_PROFILE(SMBsetatr);
1139 mode = SVAL(req->vwv+0, 0);
1140 mtime = srv_make_unix_date3(req->vwv+1);
1142 ts[1] = convert_time_t_to_timespec(mtime);
1143 status = smb_set_file_time(conn, NULL, fname,
1145 if (!NT_STATUS_IS_OK(status)) {
1146 reply_unixerror(req, ERRDOS, ERRnoaccess);
1147 END_PROFILE(SMBsetatr);
1151 if (mode != FILE_ATTRIBUTE_NORMAL) {
1152 if (VALID_STAT_OF_DIR(sbuf))
1157 if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) {
1158 reply_unixerror(req, ERRDOS, ERRnoaccess);
1159 END_PROFILE(SMBsetatr);
1164 reply_outbuf(req, 0, 0);
1166 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1168 END_PROFILE(SMBsetatr);
1172 /****************************************************************************
1174 ****************************************************************************/
1176 void reply_dskattr(struct smb_request *req)
1178 connection_struct *conn = req->conn;
1179 uint64_t dfree,dsize,bsize;
1180 START_PROFILE(SMBdskattr);
1182 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1183 reply_unixerror(req, ERRHRD, ERRgeneral);
1184 END_PROFILE(SMBdskattr);
1188 reply_outbuf(req, 5, 0);
1190 if (Protocol <= PROTOCOL_LANMAN2) {
1191 double total_space, free_space;
1192 /* we need to scale this to a number that DOS6 can handle. We
1193 use floating point so we can handle large drives on systems
1194 that don't have 64 bit integers
1196 we end up displaying a maximum of 2G to DOS systems
1198 total_space = dsize * (double)bsize;
1199 free_space = dfree * (double)bsize;
1201 dsize = (uint64_t)((total_space+63*512) / (64*512));
1202 dfree = (uint64_t)((free_space+63*512) / (64*512));
1204 if (dsize > 0xFFFF) dsize = 0xFFFF;
1205 if (dfree > 0xFFFF) dfree = 0xFFFF;
1207 SSVAL(req->outbuf,smb_vwv0,dsize);
1208 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1209 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1210 SSVAL(req->outbuf,smb_vwv3,dfree);
1212 SSVAL(req->outbuf,smb_vwv0,dsize);
1213 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1214 SSVAL(req->outbuf,smb_vwv2,512);
1215 SSVAL(req->outbuf,smb_vwv3,dfree);
1218 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1220 END_PROFILE(SMBdskattr);
1224 /****************************************************************************
1226 Can be called from SMBsearch, SMBffirst or SMBfunique.
1227 ****************************************************************************/
1229 void reply_search(struct smb_request *req)
1231 connection_struct *conn = req->conn;
1232 const char *mask = NULL;
1233 char *directory = NULL;
1239 unsigned int numentries = 0;
1240 unsigned int maxentries = 0;
1241 bool finished = False;
1247 bool check_descend = False;
1248 bool expect_close = False;
1250 bool mask_contains_wcard = False;
1251 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1252 TALLOC_CTX *ctx = talloc_tos();
1253 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1255 START_PROFILE(SMBsearch);
1258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1259 END_PROFILE(SMBsearch);
1263 if (lp_posix_pathnames()) {
1264 reply_unknown_new(req, req->cmd);
1265 END_PROFILE(SMBsearch);
1269 /* If we were called as SMBffirst then we must expect close. */
1270 if(req->cmd == SMBffirst) {
1271 expect_close = True;
1274 reply_outbuf(req, 1, 3);
1275 maxentries = SVAL(req->vwv+0, 0);
1276 dirtype = SVAL(req->vwv+1, 0);
1277 p = (const char *)req->buf + 1;
1278 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1279 &nt_status, &mask_contains_wcard);
1280 if (!NT_STATUS_IS_OK(nt_status)) {
1281 reply_nterror(req, nt_status);
1282 END_PROFILE(SMBsearch);
1286 nt_status = resolve_dfspath_wcard(ctx, conn,
1287 req->flags2 & FLAGS2_DFS_PATHNAMES,
1290 &mask_contains_wcard);
1291 if (!NT_STATUS_IS_OK(nt_status)) {
1292 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1293 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1294 ERRSRV, ERRbadpath);
1295 END_PROFILE(SMBsearch);
1298 reply_nterror(req, nt_status);
1299 END_PROFILE(SMBsearch);
1304 status_len = SVAL(p, 0);
1307 /* dirtype &= ~aDIR; */
1309 if (status_len == 0) {
1310 SMB_STRUCT_STAT sbuf;
1312 nt_status = unix_convert(ctx, conn, path, True,
1313 &directory, NULL, &sbuf);
1314 if (!NT_STATUS_IS_OK(nt_status)) {
1315 reply_nterror(req, nt_status);
1316 END_PROFILE(SMBsearch);
1320 nt_status = check_name(conn, directory);
1321 if (!NT_STATUS_IS_OK(nt_status)) {
1322 reply_nterror(req, nt_status);
1323 END_PROFILE(SMBsearch);
1327 p = strrchr_m(directory,'/');
1328 if ((p != NULL) && (*directory != '/')) {
1330 directory = talloc_strndup(ctx, directory,
1331 PTR_DIFF(p, directory));
1334 directory = talloc_strdup(ctx,".");
1338 reply_nterror(req, NT_STATUS_NO_MEMORY);
1339 END_PROFILE(SMBsearch);
1343 memset((char *)status,'\0',21);
1344 SCVAL(status,0,(dirtype & 0x1F));
1346 nt_status = dptr_create(conn,
1352 mask_contains_wcard,
1355 if (!NT_STATUS_IS_OK(nt_status)) {
1356 reply_nterror(req, nt_status);
1357 END_PROFILE(SMBsearch);
1360 dptr_num = dptr_dnum(conn->dirptr);
1364 memcpy(status,p,21);
1365 status_dirtype = CVAL(status,0) & 0x1F;
1366 if (status_dirtype != (dirtype & 0x1F)) {
1367 dirtype = status_dirtype;
1370 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1371 if (!conn->dirptr) {
1374 string_set(&conn->dirpath,dptr_path(dptr_num));
1375 mask = dptr_wcard(dptr_num);
1380 * For a 'continue' search we have no string. So
1381 * check from the initial saved string.
1383 mask_contains_wcard = ms_has_wild(mask);
1384 dirtype = dptr_attr(dptr_num);
1387 DEBUG(4,("dptr_num is %d\n",dptr_num));
1389 if ((dirtype&0x1F) == aVOLID) {
1390 char buf[DIR_STRUCT_SIZE];
1391 memcpy(buf,status,21);
1392 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1393 0,aVOLID,0,!allow_long_path_components)) {
1394 reply_nterror(req, NT_STATUS_NO_MEMORY);
1395 END_PROFILE(SMBsearch);
1398 dptr_fill(buf+12,dptr_num);
1399 if (dptr_zero(buf+12) && (status_len==0)) {
1404 if (message_push_blob(&req->outbuf,
1405 data_blob_const(buf, sizeof(buf)))
1407 reply_nterror(req, NT_STATUS_NO_MEMORY);
1408 END_PROFILE(SMBsearch);
1416 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1419 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1420 conn->dirpath,lp_dontdescend(SNUM(conn))));
1421 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1422 check_descend = True;
1425 for (i=numentries;(i<maxentries) && !finished;i++) {
1426 finished = !get_dir_entry(ctx,
1437 char buf[DIR_STRUCT_SIZE];
1438 memcpy(buf,status,21);
1439 if (!make_dir_struct(ctx,
1446 !allow_long_path_components)) {
1447 reply_nterror(req, NT_STATUS_NO_MEMORY);
1448 END_PROFILE(SMBsearch);
1451 if (!dptr_fill(buf+12,dptr_num)) {
1454 if (message_push_blob(&req->outbuf,
1455 data_blob_const(buf, sizeof(buf)))
1457 reply_nterror(req, NT_STATUS_NO_MEMORY);
1458 END_PROFILE(SMBsearch);
1468 /* If we were called as SMBffirst with smb_search_id == NULL
1469 and no entries were found then return error and close dirptr
1472 if (numentries == 0) {
1473 dptr_close(&dptr_num);
1474 } else if(expect_close && status_len == 0) {
1475 /* Close the dptr - we know it's gone */
1476 dptr_close(&dptr_num);
1479 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1480 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1481 dptr_close(&dptr_num);
1484 if ((numentries == 0) && !mask_contains_wcard) {
1485 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1486 END_PROFILE(SMBsearch);
1490 SSVAL(req->outbuf,smb_vwv0,numentries);
1491 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1492 SCVAL(smb_buf(req->outbuf),0,5);
1493 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1495 /* The replies here are never long name. */
1496 SSVAL(req->outbuf, smb_flg2,
1497 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1498 if (!allow_long_path_components) {
1499 SSVAL(req->outbuf, smb_flg2,
1500 SVAL(req->outbuf, smb_flg2)
1501 & (~FLAGS2_LONG_PATH_COMPONENTS));
1504 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1505 SSVAL(req->outbuf, smb_flg2,
1506 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1509 directory = dptr_path(dptr_num);
1512 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1513 smb_fn_name(req->cmd),
1515 directory ? directory : "./",
1520 END_PROFILE(SMBsearch);
1524 /****************************************************************************
1525 Reply to a fclose (stop directory search).
1526 ****************************************************************************/
1528 void reply_fclose(struct smb_request *req)
1536 bool path_contains_wcard = False;
1537 TALLOC_CTX *ctx = talloc_tos();
1539 START_PROFILE(SMBfclose);
1541 if (lp_posix_pathnames()) {
1542 reply_unknown_new(req, req->cmd);
1543 END_PROFILE(SMBfclose);
1547 p = (const char *)req->buf + 1;
1548 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1549 &err, &path_contains_wcard);
1550 if (!NT_STATUS_IS_OK(err)) {
1551 reply_nterror(req, err);
1552 END_PROFILE(SMBfclose);
1556 status_len = SVAL(p,0);
1559 if (status_len == 0) {
1560 reply_doserror(req, ERRSRV, ERRsrverror);
1561 END_PROFILE(SMBfclose);
1565 memcpy(status,p,21);
1567 if(dptr_fetch(status+12,&dptr_num)) {
1568 /* Close the dptr - we know it's gone */
1569 dptr_close(&dptr_num);
1572 reply_outbuf(req, 1, 0);
1573 SSVAL(req->outbuf,smb_vwv0,0);
1575 DEBUG(3,("search close\n"));
1577 END_PROFILE(SMBfclose);
1581 /****************************************************************************
1583 ****************************************************************************/
1585 void reply_open(struct smb_request *req)
1587 connection_struct *conn = req->conn;
1593 SMB_STRUCT_STAT sbuf;
1600 uint32 create_disposition;
1601 uint32 create_options = 0;
1603 TALLOC_CTX *ctx = talloc_tos();
1605 START_PROFILE(SMBopen);
1608 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1609 END_PROFILE(SMBopen);
1613 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1614 deny_mode = SVAL(req->vwv+0, 0);
1615 dos_attr = SVAL(req->vwv+1, 0);
1617 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1618 STR_TERMINATE, &status);
1619 if (!NT_STATUS_IS_OK(status)) {
1620 reply_nterror(req, status);
1621 END_PROFILE(SMBopen);
1625 if (!map_open_params_to_ntcreate(
1626 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1627 &share_mode, &create_disposition, &create_options)) {
1628 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1629 END_PROFILE(SMBopen);
1633 status = SMB_VFS_CREATE_FILE(
1636 0, /* root_dir_fid */
1638 CFF_DOS_PATH, /* create_file_flags */
1639 access_mask, /* access_mask */
1640 share_mode, /* share_access */
1641 create_disposition, /* create_disposition*/
1642 create_options, /* create_options */
1643 dos_attr, /* file_attributes */
1644 oplock_request, /* oplock_request */
1645 0, /* allocation_size */
1652 if (!NT_STATUS_IS_OK(status)) {
1653 if (open_was_deferred(req->mid)) {
1654 /* We have re-scheduled this call. */
1655 END_PROFILE(SMBopen);
1658 reply_openerror(req, status);
1659 END_PROFILE(SMBopen);
1663 size = sbuf.st_size;
1664 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1665 mtime = sbuf.st_mtime;
1668 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1669 close_file(req, fsp, ERROR_CLOSE);
1670 reply_doserror(req, ERRDOS,ERRnoaccess);
1671 END_PROFILE(SMBopen);
1675 reply_outbuf(req, 7, 0);
1676 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1677 SSVAL(req->outbuf,smb_vwv1,fattr);
1678 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1679 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1681 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1683 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1684 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1686 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1687 SCVAL(req->outbuf,smb_flg,
1688 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1691 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1692 SCVAL(req->outbuf,smb_flg,
1693 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1695 END_PROFILE(SMBopen);
1699 /****************************************************************************
1700 Reply to an open and X.
1701 ****************************************************************************/
1703 void reply_open_and_X(struct smb_request *req)
1705 connection_struct *conn = req->conn;
1710 /* Breakout the oplock request bits so we can set the
1711 reply bits separately. */
1712 int ex_oplock_request;
1713 int core_oplock_request;
1716 int smb_sattr = SVAL(req->vwv+4, 0);
1717 uint32 smb_time = make_unix_date3(req->vwv+6);
1722 SMB_STRUCT_STAT sbuf;
1726 uint64_t allocation_size;
1727 ssize_t retval = -1;
1730 uint32 create_disposition;
1731 uint32 create_options = 0;
1732 TALLOC_CTX *ctx = talloc_tos();
1734 START_PROFILE(SMBopenX);
1736 if (req->wct < 15) {
1737 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1738 END_PROFILE(SMBopenX);
1742 open_flags = SVAL(req->vwv+2, 0);
1743 deny_mode = SVAL(req->vwv+3, 0);
1744 smb_attr = SVAL(req->vwv+5, 0);
1745 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1746 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1747 oplock_request = ex_oplock_request | core_oplock_request;
1748 smb_ofun = SVAL(req->vwv+8, 0);
1749 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1751 /* If it's an IPC, pass off the pipe handler. */
1753 if (lp_nt_pipe_support()) {
1754 reply_open_pipe_and_X(conn, req);
1756 reply_doserror(req, ERRSRV, ERRaccess);
1758 END_PROFILE(SMBopenX);
1762 /* XXXX we need to handle passed times, sattr and flags */
1763 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1764 STR_TERMINATE, &status);
1765 if (!NT_STATUS_IS_OK(status)) {
1766 reply_nterror(req, status);
1767 END_PROFILE(SMBopenX);
1771 if (!map_open_params_to_ntcreate(
1772 fname, deny_mode, smb_ofun, &access_mask,
1773 &share_mode, &create_disposition, &create_options)) {
1774 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1775 END_PROFILE(SMBopenX);
1779 status = SMB_VFS_CREATE_FILE(
1782 0, /* root_dir_fid */
1784 CFF_DOS_PATH, /* create_file_flags */
1785 access_mask, /* access_mask */
1786 share_mode, /* share_access */
1787 create_disposition, /* create_disposition*/
1788 create_options, /* create_options */
1789 smb_attr, /* file_attributes */
1790 oplock_request, /* oplock_request */
1791 0, /* allocation_size */
1795 &smb_action, /* pinfo */
1798 if (!NT_STATUS_IS_OK(status)) {
1799 END_PROFILE(SMBopenX);
1800 if (open_was_deferred(req->mid)) {
1801 /* We have re-scheduled this call. */
1804 reply_openerror(req, status);
1808 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1809 if the file is truncated or created. */
1810 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1811 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1812 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1813 close_file(req, fsp, ERROR_CLOSE);
1814 reply_nterror(req, NT_STATUS_DISK_FULL);
1815 END_PROFILE(SMBopenX);
1818 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1820 close_file(req, fsp, ERROR_CLOSE);
1821 reply_nterror(req, NT_STATUS_DISK_FULL);
1822 END_PROFILE(SMBopenX);
1825 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1828 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1829 mtime = sbuf.st_mtime;
1831 close_file(req, fsp, ERROR_CLOSE);
1832 reply_doserror(req, ERRDOS, ERRnoaccess);
1833 END_PROFILE(SMBopenX);
1837 /* If the caller set the extended oplock request bit
1838 and we granted one (by whatever means) - set the
1839 correct bit for extended oplock reply.
1842 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1843 smb_action |= EXTENDED_OPLOCK_GRANTED;
1846 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1847 smb_action |= EXTENDED_OPLOCK_GRANTED;
1850 /* If the caller set the core oplock request bit
1851 and we granted one (by whatever means) - set the
1852 correct bit for core oplock reply.
1855 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1856 reply_outbuf(req, 19, 0);
1858 reply_outbuf(req, 15, 0);
1861 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1862 SCVAL(req->outbuf, smb_flg,
1863 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1866 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1867 SCVAL(req->outbuf, smb_flg,
1868 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1871 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1872 SSVAL(req->outbuf,smb_vwv3,fattr);
1873 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1874 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1876 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1878 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1879 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1880 SSVAL(req->outbuf,smb_vwv11,smb_action);
1882 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1883 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1886 END_PROFILE(SMBopenX);
1891 /****************************************************************************
1892 Reply to a SMBulogoffX.
1893 ****************************************************************************/
1895 void reply_ulogoffX(struct smb_request *req)
1899 START_PROFILE(SMBulogoffX);
1901 vuser = get_valid_user_struct(req->vuid);
1904 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1908 /* in user level security we are supposed to close any files
1909 open by this user */
1910 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1911 file_close_user(req->vuid);
1914 invalidate_vuid(req->vuid);
1916 reply_outbuf(req, 2, 0);
1918 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1920 END_PROFILE(SMBulogoffX);
1924 /****************************************************************************
1925 Reply to a mknew or a create.
1926 ****************************************************************************/
1928 void reply_mknew(struct smb_request *req)
1930 connection_struct *conn = req->conn;
1933 struct timespec ts[2];
1935 int oplock_request = 0;
1936 SMB_STRUCT_STAT sbuf;
1938 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1939 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1940 uint32 create_disposition;
1941 uint32 create_options = 0;
1942 TALLOC_CTX *ctx = talloc_tos();
1944 START_PROFILE(SMBcreate);
1947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1948 END_PROFILE(SMBcreate);
1952 fattr = SVAL(req->vwv+0, 0);
1953 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1955 ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
1958 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
1959 STR_TERMINATE, &status);
1960 if (!NT_STATUS_IS_OK(status)) {
1961 reply_nterror(req, status);
1962 END_PROFILE(SMBcreate);
1966 if (fattr & aVOLID) {
1967 DEBUG(0,("Attempt to create file (%s) with volid set - "
1968 "please report this\n", fname));
1971 if(req->cmd == SMBmknew) {
1972 /* We should fail if file exists. */
1973 create_disposition = FILE_CREATE;
1975 /* Create if file doesn't exist, truncate if it does. */
1976 create_disposition = FILE_OVERWRITE_IF;
1979 status = SMB_VFS_CREATE_FILE(
1982 0, /* root_dir_fid */
1984 CFF_DOS_PATH, /* create_file_flags */
1985 access_mask, /* access_mask */
1986 share_mode, /* share_access */
1987 create_disposition, /* create_disposition*/
1988 create_options, /* create_options */
1989 fattr, /* file_attributes */
1990 oplock_request, /* oplock_request */
1991 0, /* allocation_size */
1998 if (!NT_STATUS_IS_OK(status)) {
1999 END_PROFILE(SMBcreate);
2000 if (open_was_deferred(req->mid)) {
2001 /* We have re-scheduled this call. */
2004 reply_openerror(req, status);
2008 ts[0] = get_atimespec(&sbuf); /* atime. */
2009 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, ts, true);
2010 if (!NT_STATUS_IS_OK(status)) {
2011 END_PROFILE(SMBcreate);
2012 reply_openerror(req, status);
2016 reply_outbuf(req, 1, 0);
2017 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2019 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2020 SCVAL(req->outbuf,smb_flg,
2021 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2024 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2025 SCVAL(req->outbuf,smb_flg,
2026 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2029 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2030 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2031 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2033 END_PROFILE(SMBcreate);
2037 /****************************************************************************
2038 Reply to a create temporary file.
2039 ****************************************************************************/
2041 void reply_ctemp(struct smb_request *req)
2043 connection_struct *conn = req->conn;
2049 SMB_STRUCT_STAT sbuf;
2052 TALLOC_CTX *ctx = talloc_tos();
2054 START_PROFILE(SMBctemp);
2057 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2058 END_PROFILE(SMBctemp);
2062 fattr = SVAL(req->vwv+0, 0);
2063 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2065 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2066 STR_TERMINATE, &status);
2067 if (!NT_STATUS_IS_OK(status)) {
2068 reply_nterror(req, status);
2069 END_PROFILE(SMBctemp);
2073 fname = talloc_asprintf(ctx,
2077 fname = talloc_strdup(ctx, "TMXXXXXX");
2081 reply_nterror(req, NT_STATUS_NO_MEMORY);
2082 END_PROFILE(SMBctemp);
2086 status = resolve_dfspath(ctx, conn,
2087 req->flags2 & FLAGS2_DFS_PATHNAMES,
2090 if (!NT_STATUS_IS_OK(status)) {
2091 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2092 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2093 ERRSRV, ERRbadpath);
2094 END_PROFILE(SMBctemp);
2097 reply_nterror(req, status);
2098 END_PROFILE(SMBctemp);
2102 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
2103 if (!NT_STATUS_IS_OK(status)) {
2104 reply_nterror(req, status);
2105 END_PROFILE(SMBctemp);
2109 status = check_name(conn, fname);
2110 if (!NT_STATUS_IS_OK(status)) {
2111 reply_nterror(req, status);
2112 END_PROFILE(SMBctemp);
2116 tmpfd = smb_mkstemp(fname);
2118 reply_unixerror(req, ERRDOS, ERRnoaccess);
2119 END_PROFILE(SMBctemp);
2123 SMB_VFS_STAT(conn,fname,&sbuf);
2125 /* We should fail if file does not exist. */
2126 status = SMB_VFS_CREATE_FILE(
2129 0, /* root_dir_fid */
2131 0, /* create_file_flags */
2132 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2133 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2134 FILE_OPEN, /* create_disposition*/
2135 0, /* create_options */
2136 fattr, /* file_attributes */
2137 oplock_request, /* oplock_request */
2138 0, /* allocation_size */
2145 /* close fd from smb_mkstemp() */
2148 if (!NT_STATUS_IS_OK(status)) {
2149 if (open_was_deferred(req->mid)) {
2150 /* We have re-scheduled this call. */
2151 END_PROFILE(SMBctemp);
2154 reply_openerror(req, status);
2155 END_PROFILE(SMBctemp);
2159 reply_outbuf(req, 1, 0);
2160 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2162 /* the returned filename is relative to the directory */
2163 s = strrchr_m(fsp->fsp_name, '/');
2171 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2172 thing in the byte section. JRA */
2173 SSVALS(p, 0, -1); /* what is this? not in spec */
2175 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2177 reply_nterror(req, NT_STATUS_NO_MEMORY);
2178 END_PROFILE(SMBctemp);
2182 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2183 SCVAL(req->outbuf, smb_flg,
2184 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2187 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2188 SCVAL(req->outbuf, smb_flg,
2189 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2192 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2193 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2194 fsp->fh->fd, (unsigned int)sbuf.st_mode ) );
2196 END_PROFILE(SMBctemp);
2200 /*******************************************************************
2201 Check if a user is allowed to rename a file.
2202 ********************************************************************/
2204 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2205 uint16 dirtype, SMB_STRUCT_STAT *pst)
2209 if (!CAN_WRITE(conn)) {
2210 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2213 fmode = dos_mode(conn, fsp->fsp_name, pst);
2214 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2215 return NT_STATUS_NO_SUCH_FILE;
2218 if (S_ISDIR(pst->st_mode)) {
2219 return NT_STATUS_OK;
2222 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2223 return NT_STATUS_OK;
2226 return NT_STATUS_ACCESS_DENIED;
2229 /*******************************************************************
2230 * unlink a file with all relevant access checks
2231 *******************************************************************/
2233 static NTSTATUS do_unlink(connection_struct *conn,
2234 struct smb_request *req,
2238 SMB_STRUCT_STAT sbuf;
2241 uint32 dirtype_orig = dirtype;
2244 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2246 if (!CAN_WRITE(conn)) {
2247 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2250 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2251 return map_nt_error_from_unix(errno);
2254 fattr = dos_mode(conn,fname,&sbuf);
2256 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2257 dirtype = aDIR|aARCH|aRONLY;
2260 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2262 return NT_STATUS_NO_SUCH_FILE;
2265 if (!dir_check_ftype(conn, fattr, dirtype)) {
2267 return NT_STATUS_FILE_IS_A_DIRECTORY;
2269 return NT_STATUS_NO_SUCH_FILE;
2272 if (dirtype_orig & 0x8000) {
2273 /* These will never be set for POSIX. */
2274 return NT_STATUS_NO_SUCH_FILE;
2278 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2279 return NT_STATUS_FILE_IS_A_DIRECTORY;
2282 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2283 return NT_STATUS_NO_SUCH_FILE;
2286 if (dirtype & 0xFF00) {
2287 /* These will never be set for POSIX. */
2288 return NT_STATUS_NO_SUCH_FILE;
2293 return NT_STATUS_NO_SUCH_FILE;
2296 /* Can't delete a directory. */
2298 return NT_STATUS_FILE_IS_A_DIRECTORY;
2303 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2304 return NT_STATUS_OBJECT_NAME_INVALID;
2305 #endif /* JRATEST */
2307 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2309 On a Windows share, a file with read-only dosmode can be opened with
2310 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2311 fails with NT_STATUS_CANNOT_DELETE error.
2313 This semantic causes a problem that a user can not
2314 rename a file with read-only dosmode on a Samba share
2315 from a Windows command prompt (i.e. cmd.exe, but can rename
2316 from Windows Explorer).
2319 if (!lp_delete_readonly(SNUM(conn))) {
2320 if (fattr & aRONLY) {
2321 return NT_STATUS_CANNOT_DELETE;
2325 /* On open checks the open itself will check the share mode, so
2326 don't do it here as we'll get it wrong. */
2328 status = SMB_VFS_CREATE_FILE
2331 0, /* root_dir_fid */
2333 0, /* create_file_flags */
2334 DELETE_ACCESS, /* access_mask */
2335 FILE_SHARE_NONE, /* share_access */
2336 FILE_OPEN, /* create_disposition*/
2337 FILE_NON_DIRECTORY_FILE, /* create_options */
2338 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2339 0, /* oplock_request */
2340 0, /* allocation_size */
2347 if (!NT_STATUS_IS_OK(status)) {
2348 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2349 nt_errstr(status)));
2353 /* The set is across all open files on this dev/inode pair. */
2354 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2355 close_file(req, fsp, NORMAL_CLOSE);
2356 return NT_STATUS_ACCESS_DENIED;
2359 return close_file(req, fsp, NORMAL_CLOSE);
2362 /****************************************************************************
2363 The guts of the unlink command, split out so it may be called by the NT SMB
2365 ****************************************************************************/
2367 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2368 uint32 dirtype, const char *name_in, bool has_wild)
2370 const char *directory = NULL;
2375 NTSTATUS status = NT_STATUS_OK;
2376 SMB_STRUCT_STAT sbuf;
2377 TALLOC_CTX *ctx = talloc_tos();
2379 status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
2380 if (!NT_STATUS_IS_OK(status)) {
2384 p = strrchr_m(name,'/');
2386 directory = talloc_strdup(ctx, ".");
2388 return NT_STATUS_NO_MEMORY;
2398 * We should only check the mangled cache
2399 * here if unix_convert failed. This means
2400 * that the path in 'mask' doesn't exist
2401 * on the file system and so we need to look
2402 * for a possible mangle. This patch from
2403 * Tine Smukavec <valentin.smukavec@hermes.si>.
2406 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
2407 char *new_mask = NULL;
2408 mangle_lookup_name_from_8_3(ctx,
2418 directory = talloc_asprintf(ctx,
2423 return NT_STATUS_NO_MEMORY;
2426 dirtype = FILE_ATTRIBUTE_NORMAL;
2429 status = check_name(conn, directory);
2430 if (!NT_STATUS_IS_OK(status)) {
2434 status = do_unlink(conn, req, directory, dirtype);
2435 if (!NT_STATUS_IS_OK(status)) {
2441 struct smb_Dir *dir_hnd = NULL;
2445 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2446 return NT_STATUS_OBJECT_NAME_INVALID;
2449 if (strequal(mask,"????????.???")) {
2454 status = check_name(conn, directory);
2455 if (!NT_STATUS_IS_OK(status)) {
2459 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2461 if (dir_hnd == NULL) {
2462 return map_nt_error_from_unix(errno);
2465 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2466 the pattern matches against the long name, otherwise the short name
2467 We don't implement this yet XXXX
2470 status = NT_STATUS_NO_SUCH_FILE;
2472 while ((dname = ReadDirName(dir_hnd, &offset))) {
2476 if (!is_visible_file(conn, directory, dname, &st, True)) {
2480 /* Quick check for "." and ".." */
2481 if (ISDOT(dname) || ISDOTDOT(dname)) {
2485 if(!mask_match(dname, mask, conn->case_sensitive)) {
2489 fname = talloc_asprintf(ctx, "%s/%s",
2493 return NT_STATUS_NO_MEMORY;
2496 status = check_name(conn, fname);
2497 if (!NT_STATUS_IS_OK(status)) {
2498 TALLOC_FREE(dir_hnd);
2502 status = do_unlink(conn, req, fname, dirtype);
2503 if (!NT_STATUS_IS_OK(status)) {
2509 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2514 TALLOC_FREE(dir_hnd);
2517 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2518 status = map_nt_error_from_unix(errno);
2524 /****************************************************************************
2526 ****************************************************************************/
2528 void reply_unlink(struct smb_request *req)
2530 connection_struct *conn = req->conn;
2534 bool path_contains_wcard = False;
2535 TALLOC_CTX *ctx = talloc_tos();
2537 START_PROFILE(SMBunlink);
2540 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2541 END_PROFILE(SMBunlink);
2545 dirtype = SVAL(req->vwv+0, 0);
2547 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2548 STR_TERMINATE, &status,
2549 &path_contains_wcard);
2550 if (!NT_STATUS_IS_OK(status)) {
2551 reply_nterror(req, status);
2552 END_PROFILE(SMBunlink);
2556 status = resolve_dfspath_wcard(ctx, conn,
2557 req->flags2 & FLAGS2_DFS_PATHNAMES,
2560 &path_contains_wcard);
2561 if (!NT_STATUS_IS_OK(status)) {
2562 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2563 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2564 ERRSRV, ERRbadpath);
2565 END_PROFILE(SMBunlink);
2568 reply_nterror(req, status);
2569 END_PROFILE(SMBunlink);
2573 DEBUG(3,("reply_unlink : %s\n",name));
2575 status = unlink_internals(conn, req, dirtype, name,
2576 path_contains_wcard);
2577 if (!NT_STATUS_IS_OK(status)) {
2578 if (open_was_deferred(req->mid)) {
2579 /* We have re-scheduled this call. */
2580 END_PROFILE(SMBunlink);
2583 reply_nterror(req, status);
2584 END_PROFILE(SMBunlink);
2588 reply_outbuf(req, 0, 0);
2589 END_PROFILE(SMBunlink);
2594 /****************************************************************************
2596 ****************************************************************************/
2598 static void fail_readraw(void)
2600 const char *errstr = talloc_asprintf(talloc_tos(),
2601 "FAIL ! reply_readbraw: socket write fail (%s)",
2606 exit_server_cleanly(errstr);
2609 /****************************************************************************
2610 Fake (read/write) sendfile. Returns -1 on read or write fail.
2611 ****************************************************************************/
2613 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2617 size_t tosend = nread;
2624 bufsize = MIN(nread, 65536);
2626 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2630 while (tosend > 0) {
2634 if (tosend > bufsize) {
2639 ret = read_file(fsp,buf,startpos,cur_read);
2645 /* If we had a short read, fill with zeros. */
2646 if (ret < cur_read) {
2647 memset(buf, '\0', cur_read - ret);
2650 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2655 startpos += cur_read;
2659 return (ssize_t)nread;
2662 /****************************************************************************
2663 Return a readbraw error (4 bytes of zero).
2664 ****************************************************************************/
2666 static void reply_readbraw_error(void)
2670 if (write_data(smbd_server_fd(),header,4) != 4) {
2675 /****************************************************************************
2676 Use sendfile in readbraw.
2677 ****************************************************************************/
2679 void send_file_readbraw(connection_struct *conn,
2685 char *outbuf = NULL;
2688 #if defined(WITH_SENDFILE)
2690 * We can only use sendfile on a non-chained packet
2691 * but we can use on a non-oplocked file. tridge proved this
2692 * on a train in Germany :-). JRA.
2693 * reply_readbraw has already checked the length.
2696 if ( (chain_size == 0) && (nread > 0) && (fsp->base_fsp == NULL) &&
2697 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2699 DATA_BLOB header_blob;
2701 _smb_setlen(header,nread);
2702 header_blob = data_blob_const(header, 4);
2704 if (SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2705 &header_blob, startpos, nread) == -1) {
2706 /* Returning ENOSYS means no data at all was sent.
2707 * Do this as a normal read. */
2708 if (errno == ENOSYS) {
2709 goto normal_readbraw;
2713 * Special hack for broken Linux with no working sendfile. If we
2714 * return EINTR we sent the header but not the rest of the data.
2715 * Fake this up by doing read/write calls.
2717 if (errno == EINTR) {
2718 /* Ensure we don't do this again. */
2719 set_use_sendfile(SNUM(conn), False);
2720 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2722 if (fake_sendfile(fsp, startpos, nread) == -1) {
2723 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2724 fsp->fsp_name, strerror(errno) ));
2725 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2730 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2731 fsp->fsp_name, strerror(errno) ));
2732 exit_server_cleanly("send_file_readbraw sendfile failed");
2741 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2743 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2744 (unsigned)(nread+4)));
2745 reply_readbraw_error();
2750 ret = read_file(fsp,outbuf+4,startpos,nread);
2751 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2760 _smb_setlen(outbuf,ret);
2761 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2764 TALLOC_FREE(outbuf);
2767 /****************************************************************************
2768 Reply to a readbraw (core+ protocol).
2769 ****************************************************************************/
2771 void reply_readbraw(struct smb_request *req)
2773 connection_struct *conn = req->conn;
2774 ssize_t maxcount,mincount;
2781 START_PROFILE(SMBreadbraw);
2783 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
2784 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2785 "raw reads/writes are disallowed.");
2789 reply_readbraw_error();
2790 END_PROFILE(SMBreadbraw);
2795 * Special check if an oplock break has been issued
2796 * and the readraw request croses on the wire, we must
2797 * return a zero length response here.
2800 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2803 * We have to do a check_fsp by hand here, as
2804 * we must always return 4 zero bytes on error,
2808 if (!fsp || !conn || conn != fsp->conn ||
2809 req->vuid != fsp->vuid ||
2810 fsp->is_directory || fsp->fh->fd == -1) {
2812 * fsp could be NULL here so use the value from the packet. JRA.
2814 DEBUG(3,("reply_readbraw: fnum %d not valid "
2816 (int)SVAL(req->vwv+0, 0)));
2817 reply_readbraw_error();
2818 END_PROFILE(SMBreadbraw);
2822 /* Do a "by hand" version of CHECK_READ. */
2823 if (!(fsp->can_read ||
2824 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2825 (fsp->access_mask & FILE_EXECUTE)))) {
2826 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2827 (int)SVAL(req->vwv+0, 0)));
2828 reply_readbraw_error();
2829 END_PROFILE(SMBreadbraw);
2833 flush_write_cache(fsp, READRAW_FLUSH);
2835 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
2836 if(req->wct == 10) {
2838 * This is a large offset (64 bit) read.
2840 #ifdef LARGE_SMB_OFF_T
2842 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
2844 #else /* !LARGE_SMB_OFF_T */
2847 * Ensure we haven't been sent a >32 bit offset.
2850 if(IVAL(req->vwv+8, 0) != 0) {
2851 DEBUG(0,("reply_readbraw: large offset "
2852 "(%x << 32) used and we don't support "
2853 "64 bit offsets.\n",
2854 (unsigned int)IVAL(req->vwv+8, 0) ));
2855 reply_readbraw_error();
2856 END_PROFILE(SMBreadbraw);
2860 #endif /* LARGE_SMB_OFF_T */
2863 DEBUG(0,("reply_readbraw: negative 64 bit "
2864 "readraw offset (%.0f) !\n",
2865 (double)startpos ));
2866 reply_readbraw_error();
2867 END_PROFILE(SMBreadbraw);
2872 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
2873 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
2875 /* ensure we don't overrun the packet size */
2876 maxcount = MIN(65535,maxcount);
2878 if (is_locked(fsp,(uint32)req->smbpid,
2882 reply_readbraw_error();
2883 END_PROFILE(SMBreadbraw);
2887 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
2891 if (startpos >= size) {
2894 nread = MIN(maxcount,(size - startpos));
2897 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2898 if (nread < mincount)
2902 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2903 "min=%lu nread=%lu\n",
2904 fsp->fnum, (double)startpos,
2905 (unsigned long)maxcount,
2906 (unsigned long)mincount,
2907 (unsigned long)nread ) );
2909 send_file_readbraw(conn, fsp, startpos, nread, mincount);
2911 DEBUG(5,("reply_readbraw finished\n"));
2912 END_PROFILE(SMBreadbraw);
2916 #define DBGC_CLASS DBGC_LOCKING
2918 /****************************************************************************
2919 Reply to a lockread (core+ protocol).
2920 ****************************************************************************/
2922 void reply_lockread(struct smb_request *req)
2924 connection_struct *conn = req->conn;
2931 struct byte_range_lock *br_lck = NULL;
2934 START_PROFILE(SMBlockread);
2937 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2938 END_PROFILE(SMBlockread);
2942 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2944 if (!check_fsp(conn, req, fsp)) {
2945 END_PROFILE(SMBlockread);
2949 if (!CHECK_READ(fsp,req)) {
2950 reply_doserror(req, ERRDOS, ERRbadaccess);
2951 END_PROFILE(SMBlockread);
2955 release_level_2_oplocks_on_change(fsp);
2957 numtoread = SVAL(req->vwv+1, 0);
2958 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
2960 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
2962 reply_outbuf(req, 5, numtoread + 3);
2964 data = smb_buf(req->outbuf) + 3;
2967 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2968 * protocol request that predates the read/write lock concept.
2969 * Thus instead of asking for a read lock here we need to ask
2970 * for a write lock. JRA.
2971 * Note that the requested lock size is unaffected by max_recv.
2974 br_lck = do_lock(smbd_messaging_context(),
2977 (uint64_t)numtoread,
2981 False, /* Non-blocking lock. */
2984 TALLOC_FREE(br_lck);
2986 if (NT_STATUS_V(status)) {
2987 reply_nterror(req, status);
2988 END_PROFILE(SMBlockread);
2993 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2996 if (numtoread > max_recv) {
2997 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2998 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2999 (unsigned int)numtoread, (unsigned int)max_recv ));
3000 numtoread = MIN(numtoread,max_recv);
3002 nread = read_file(fsp,data,startpos,numtoread);
3005 reply_unixerror(req, ERRDOS, ERRnoaccess);
3006 END_PROFILE(SMBlockread);
3010 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3012 SSVAL(req->outbuf,smb_vwv0,nread);
3013 SSVAL(req->outbuf,smb_vwv5,nread+3);
3014 p = smb_buf(req->outbuf);
3015 SCVAL(p,0,0); /* pad byte. */
3018 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3019 fsp->fnum, (int)numtoread, (int)nread));
3021 END_PROFILE(SMBlockread);
3026 #define DBGC_CLASS DBGC_ALL
3028 /****************************************************************************
3030 ****************************************************************************/
3032 void reply_read(struct smb_request *req)
3034 connection_struct *conn = req->conn;
3042 START_PROFILE(SMBread);
3045 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3046 END_PROFILE(SMBread);
3050 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3052 if (!check_fsp(conn, req, fsp)) {
3053 END_PROFILE(SMBread);
3057 if (!CHECK_READ(fsp,req)) {
3058 reply_doserror(req, ERRDOS, ERRbadaccess);
3059 END_PROFILE(SMBread);
3063 numtoread = SVAL(req->vwv+1, 0);
3064 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3066 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3069 * The requested read size cannot be greater than max_recv. JRA.
3071 if (numtoread > max_recv) {
3072 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3073 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3074 (unsigned int)numtoread, (unsigned int)max_recv ));
3075 numtoread = MIN(numtoread,max_recv);
3078 reply_outbuf(req, 5, numtoread+3);
3080 data = smb_buf(req->outbuf) + 3;
3082 if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtoread,
3083 (uint64_t)startpos, READ_LOCK)) {
3084 reply_doserror(req, ERRDOS,ERRlock);
3085 END_PROFILE(SMBread);
3090 nread = read_file(fsp,data,startpos,numtoread);
3093 reply_unixerror(req, ERRDOS,ERRnoaccess);
3094 END_PROFILE(SMBread);
3098 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3100 SSVAL(req->outbuf,smb_vwv0,nread);
3101 SSVAL(req->outbuf,smb_vwv5,nread+3);
3102 SCVAL(smb_buf(req->outbuf),0,1);
3103 SSVAL(smb_buf(req->outbuf),1,nread);
3105 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3106 fsp->fnum, (int)numtoread, (int)nread ) );
3108 END_PROFILE(SMBread);
3112 /****************************************************************************
3114 ****************************************************************************/
3116 static int setup_readX_header(char *outbuf, size_t smb_maxcnt)
3121 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3122 data = smb_buf(outbuf);
3124 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3126 SCVAL(outbuf,smb_vwv0,0xFF);
3127 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3128 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3129 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
3130 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3131 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
3132 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3133 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3137 /****************************************************************************
3138 Reply to a read and X - possibly using sendfile.
3139 ****************************************************************************/
3141 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3142 files_struct *fsp, SMB_OFF_T startpos,
3145 SMB_STRUCT_STAT sbuf;
3148 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3149 reply_unixerror(req, ERRDOS, ERRnoaccess);
3153 if (startpos > sbuf.st_size) {
3155 } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
3156 smb_maxcnt = (sbuf.st_size - startpos);
3159 if (smb_maxcnt == 0) {
3163 #if defined(WITH_SENDFILE)
3165 * We can only use sendfile on a non-chained packet
3166 * but we can use on a non-oplocked file. tridge proved this
3167 * on a train in Germany :-). JRA.
3170 if ((chain_size == 0) && (CVAL(req->vwv+0, 0) == 0xFF) &&
3171 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3172 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
3173 uint8 headerbuf[smb_size + 12 * 2];
3177 * Set up the packet header before send. We
3178 * assume here the sendfile will work (get the
3179 * correct amount of data).
3182 header = data_blob_const(headerbuf, sizeof(headerbuf));
3184 construct_reply_common_req(req, (char *)headerbuf);
3185 setup_readX_header((char *)headerbuf, smb_maxcnt);
3187 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3188 /* Returning ENOSYS or EINVAL means no data at all was sent.
3189 Do this as a normal read. */
3190 if (errno == ENOSYS || errno == EINVAL) {
3195 * Special hack for broken Linux with no working sendfile. If we
3196 * return EINTR we sent the header but not the rest of the data.
3197 * Fake this up by doing read/write calls.
3200 if (errno == EINTR) {
3201 /* Ensure we don't do this again. */
3202 set_use_sendfile(SNUM(conn), False);
3203 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3204 nread = fake_sendfile(fsp, startpos,
3207 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3208 fsp->fsp_name, strerror(errno) ));
3209 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3211 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3212 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3213 /* No outbuf here means successful sendfile. */
3214 TALLOC_FREE(req->outbuf);
3218 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3219 fsp->fsp_name, strerror(errno) ));
3220 exit_server_cleanly("send_file_readX sendfile failed");
3223 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3224 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3225 /* No outbuf here means successful sendfile. */
3226 TALLOC_FREE(req->outbuf);
3233 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3234 uint8 headerbuf[smb_size + 2*12];
3236 construct_reply_common_req(req, (char *)headerbuf);
3237 setup_readX_header((char *)headerbuf, smb_maxcnt);
3239 /* Send out the header. */
3240 if (write_data(smbd_server_fd(), (char *)headerbuf,
3241 sizeof(headerbuf)) != sizeof(headerbuf)) {
3242 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3243 fsp->fsp_name, strerror(errno) ));
3244 exit_server_cleanly("send_file_readX sendfile failed");
3246 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3248 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3249 fsp->fsp_name, strerror(errno) ));
3250 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3252 TALLOC_FREE(req->outbuf);
3256 reply_outbuf(req, 12, smb_maxcnt);
3258 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3260 reply_unixerror(req, ERRDOS, ERRnoaccess);
3264 setup_readX_header((char *)req->outbuf, nread);
3266 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3267 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3272 /****************************************************************************
3273 Reply to a read and X.
3274 ****************************************************************************/
3276 void reply_read_and_X(struct smb_request *req)
3278 connection_struct *conn = req->conn;
3282 bool big_readX = False;
3284 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3287 START_PROFILE(SMBreadX);
3289 if ((req->wct != 10) && (req->wct != 12)) {
3290 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3294 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3295 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3296 smb_maxcnt = SVAL(req->vwv+5, 0);
3298 /* If it's an IPC, pass off the pipe handler. */
3300 reply_pipe_read_and_X(req);
3301 END_PROFILE(SMBreadX);
3305 if (!check_fsp(conn, req, fsp)) {
3306 END_PROFILE(SMBreadX);
3310 if (!CHECK_READ(fsp,req)) {
3311 reply_doserror(req, ERRDOS,ERRbadaccess);
3312 END_PROFILE(SMBreadX);
3316 if (global_client_caps & CAP_LARGE_READX) {
3317 size_t upper_size = SVAL(req->vwv+7, 0);
3318 smb_maxcnt |= (upper_size<<16);
3319 if (upper_size > 1) {
3320 /* Can't do this on a chained packet. */
3321 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3322 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3323 END_PROFILE(SMBreadX);
3326 /* We currently don't do this on signed or sealed data. */
3327 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
3328 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3329 END_PROFILE(SMBreadX);
3332 /* Is there room in the reply for this data ? */
3333 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3335 NT_STATUS_INVALID_PARAMETER);
3336 END_PROFILE(SMBreadX);
3343 if (req->wct == 12) {
3344 #ifdef LARGE_SMB_OFF_T
3346 * This is a large offset (64 bit) read.
3348 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3350 #else /* !LARGE_SMB_OFF_T */
3353 * Ensure we haven't been sent a >32 bit offset.
3356 if(IVAL(req->vwv+10, 0) != 0) {
3357 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3358 "used and we don't support 64 bit offsets.\n",
3359 (unsigned int)IVAL(req->vwv+10, 0) ));
3360 END_PROFILE(SMBreadX);
3361 reply_doserror(req, ERRDOS, ERRbadaccess);
3365 #endif /* LARGE_SMB_OFF_T */
3369 if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)smb_maxcnt,
3370 (uint64_t)startpos, READ_LOCK)) {
3371 END_PROFILE(SMBreadX);
3372 reply_doserror(req, ERRDOS, ERRlock);
3377 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3378 END_PROFILE(SMBreadX);
3382 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3384 END_PROFILE(SMBreadX);
3388 /****************************************************************************
3389 Error replies to writebraw must have smb_wct == 1. Fix this up.
3390 ****************************************************************************/
3392 void error_to_writebrawerr(struct smb_request *req)
3394 uint8 *old_outbuf = req->outbuf;
3396 reply_outbuf(req, 1, 0);
3398 memcpy(req->outbuf, old_outbuf, smb_size);
3399 TALLOC_FREE(old_outbuf);
3402 /****************************************************************************
3403 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3404 ****************************************************************************/
3406 void reply_writebraw(struct smb_request *req)
3408 connection_struct *conn = req->conn;
3411 ssize_t total_written=0;
3412 size_t numtowrite=0;
3420 START_PROFILE(SMBwritebraw);
3423 * If we ever reply with an error, it must have the SMB command
3424 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3427 SCVAL(req->inbuf,smb_com,SMBwritec);
3429 if (srv_is_signing_active()) {
3430 END_PROFILE(SMBwritebraw);
3431 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3432 "raw reads/writes are disallowed.");
3435 if (req->wct < 12) {
3436 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3437 error_to_writebrawerr(req);
3438 END_PROFILE(SMBwritebraw);
3442 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3443 if (!check_fsp(conn, req, fsp)) {
3444 error_to_writebrawerr(req);
3445 END_PROFILE(SMBwritebraw);
3449 if (!CHECK_WRITE(fsp)) {
3450 reply_doserror(req, ERRDOS, ERRbadaccess);
3451 error_to_writebrawerr(req);
3452 END_PROFILE(SMBwritebraw);
3456 tcount = IVAL(req->vwv+1, 0);
3457 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3458 write_through = BITSETW(req->vwv+7,0);
3460 /* We have to deal with slightly different formats depending
3461 on whether we are using the core+ or lanman1.0 protocol */
3463 if(Protocol <= PROTOCOL_COREPLUS) {
3464 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3465 data = smb_buf(req->inbuf);
3467 numtowrite = SVAL(req->vwv+10, 0);
3468 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3471 /* Ensure we don't write bytes past the end of this packet. */
3472 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3473 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3474 error_to_writebrawerr(req);
3475 END_PROFILE(SMBwritebraw);
3479 if (is_locked(fsp,(uint32)req->smbpid,(uint64_t)tcount,
3480 (uint64_t)startpos, WRITE_LOCK)) {
3481 reply_doserror(req, ERRDOS, ERRlock);
3482 error_to_writebrawerr(req);
3483 END_PROFILE(SMBwritebraw);
3488 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3491 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3492 "wrote=%d sync=%d\n",
3493 fsp->fnum, (double)startpos, (int)numtowrite,
3494 (int)nwritten, (int)write_through));
3496 if (nwritten < (ssize_t)numtowrite) {
3497 reply_unixerror(req, ERRHRD, ERRdiskfull);
3498 error_to_writebrawerr(req);
3499 END_PROFILE(SMBwritebraw);
3503 total_written = nwritten;
3505 /* Allocate a buffer of 64k + length. */
3506 buf = TALLOC_ARRAY(NULL, char, 65540);
3508 reply_doserror(req, ERRDOS, ERRnomem);
3509 error_to_writebrawerr(req);
3510 END_PROFILE(SMBwritebraw);
3514 /* Return a SMBwritebraw message to the redirector to tell
3515 * it to send more bytes */
3517 memcpy(buf, req->inbuf, smb_size);
3518 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3519 SCVAL(buf,smb_com,SMBwritebraw);
3520 SSVALS(buf,smb_vwv0,0xFFFF);
3522 if (!srv_send_smb(smbd_server_fd(),
3524 IS_CONN_ENCRYPTED(conn))) {
3525 exit_server_cleanly("reply_writebraw: srv_send_smb "
3529 /* Now read the raw data into the buffer and write it */
3530 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3532 if (!NT_STATUS_IS_OK(status)) {
3533 exit_server_cleanly("secondary writebraw failed");
3536 /* Set up outbuf to return the correct size */
3537 reply_outbuf(req, 1, 0);
3539 if (numtowrite != 0) {
3541 if (numtowrite > 0xFFFF) {
3542 DEBUG(0,("reply_writebraw: Oversize secondary write "
3543 "raw requested (%u). Terminating\n",
3544 (unsigned int)numtowrite ));
3545 exit_server_cleanly("secondary writebraw failed");
3548 if (tcount > nwritten+numtowrite) {
3549 DEBUG(3,("reply_writebraw: Client overestimated the "
3551 (int)tcount,(int)nwritten,(int)numtowrite));
3554 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3556 if (!NT_STATUS_IS_OK(status)) {
3557 DEBUG(0,("reply_writebraw: Oversize secondary write "
3558 "raw read failed (%s). Terminating\n",
3559 nt_errstr(status)));
3560 exit_server_cleanly("secondary writebraw failed");
3563 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3564 if (nwritten == -1) {
3566 reply_unixerror(req, ERRHRD, ERRdiskfull);
3567 error_to_writebrawerr(req);
3568 END_PROFILE(SMBwritebraw);
3572 if (nwritten < (ssize_t)numtowrite) {
3573 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3574 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3578 total_written += nwritten;
3583 SSVAL(req->outbuf,smb_vwv0,total_written);
3585 status = sync_file(conn, fsp, write_through);
3586 if (!NT_STATUS_IS_OK(status)) {
3587 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3588 fsp->fsp_name, nt_errstr(status) ));
3589 reply_nterror(req, status);
3590 error_to_writebrawerr(req);
3591 END_PROFILE(SMBwritebraw);
3595 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3597 fsp->fnum, (double)startpos, (int)numtowrite,
3598 (int)total_written));
3600 /* We won't return a status if write through is not selected - this
3601 * follows what WfWg does */
3602 END_PROFILE(SMBwritebraw);
3604 if (!write_through && total_written==tcount) {
3606 #if RABBIT_PELLET_FIX
3608 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3609 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3612 if (!send_keepalive(smbd_server_fd())) {
3613 exit_server_cleanly("reply_writebraw: send of "
3614 "keepalive failed");
3617 TALLOC_FREE(req->outbuf);
3623 #define DBGC_CLASS DBGC_LOCKING
3625 /****************************************************************************
3626 Reply to a writeunlock (core+).
3627 ****************************************************************************/
3629 void reply_writeunlock(struct smb_request *req)
3631 connection_struct *conn = req->conn;
3632 ssize_t nwritten = -1;
3636 NTSTATUS status = NT_STATUS_OK;
3639 START_PROFILE(SMBwriteunlock);
3642 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3643 END_PROFILE(SMBwriteunlock);
3647 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3649 if (!check_fsp(conn, req, fsp)) {
3650 END_PROFILE(SMBwriteunlock);
3654 if (!CHECK_WRITE(fsp)) {
3655 reply_doserror(req, ERRDOS,ERRbadaccess);
3656 END_PROFILE(SMBwriteunlock);
3660 numtowrite = SVAL(req->vwv+1, 0);
3661 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3662 data = (const char *)req->buf + 3;
3665 && is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
3666 (uint64_t)startpos, WRITE_LOCK)) {
3667 reply_doserror(req, ERRDOS, ERRlock);
3668 END_PROFILE(SMBwriteunlock);
3672 /* The special X/Open SMB protocol handling of
3673 zero length writes is *NOT* done for
3675 if(numtowrite == 0) {
3678 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3681 status = sync_file(conn, fsp, False /* write through */);
3682 if (!NT_STATUS_IS_OK(status)) {
3683 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3684 fsp->fsp_name, nt_errstr(status) ));
3685 reply_nterror(req, status);
3686 END_PROFILE(SMBwriteunlock);
3690 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3691 reply_unixerror(req, ERRHRD, ERRdiskfull);
3692 END_PROFILE(SMBwriteunlock);
3697 status = do_unlock(smbd_messaging_context(),
3700 (uint64_t)numtowrite,
3704 if (NT_STATUS_V(status)) {
3705 reply_nterror(req, status);
3706 END_PROFILE(SMBwriteunlock);
3711 reply_outbuf(req, 1, 0);
3713 SSVAL(req->outbuf,smb_vwv0,nwritten);
3715 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3716 fsp->fnum, (int)numtowrite, (int)nwritten));
3718 END_PROFILE(SMBwriteunlock);
3723 #define DBGC_CLASS DBGC_ALL
3725 /****************************************************************************
3727 ****************************************************************************/
3729 void reply_write(struct smb_request *req)
3731 connection_struct *conn = req->conn;
3733 ssize_t nwritten = -1;
3739 START_PROFILE(SMBwrite);
3742 END_PROFILE(SMBwrite);
3743 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3747 /* If it's an IPC, pass off the pipe handler. */
3749 reply_pipe_write(req);
3750 END_PROFILE(SMBwrite);
3754 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3756 if (!check_fsp(conn, req, fsp)) {
3757 END_PROFILE(SMBwrite);
3761 if (!CHECK_WRITE(fsp)) {
3762 reply_doserror(req, ERRDOS, ERRbadaccess);
3763 END_PROFILE(SMBwrite);
3767 numtowrite = SVAL(req->vwv+1, 0);
3768 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3769 data = (const char *)req->buf + 3;
3771 if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
3772 (uint64_t)startpos, WRITE_LOCK)) {
3773 reply_doserror(req, ERRDOS, ERRlock);
3774 END_PROFILE(SMBwrite);
3779 * X/Open SMB protocol says that if smb_vwv1 is
3780 * zero then the file size should be extended or
3781 * truncated to the size given in smb_vwv[2-3].
3784 if(numtowrite == 0) {
3786 * This is actually an allocate call, and set EOF. JRA.
3788 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3790 reply_nterror(req, NT_STATUS_DISK_FULL);
3791 END_PROFILE(SMBwrite);
3794 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3796 reply_nterror(req, NT_STATUS_DISK_FULL);
3797 END_PROFILE(SMBwrite);
3800 trigger_write_time_update_immediate(fsp);
3802 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3805 status = sync_file(conn, fsp, False);
3806 if (!NT_STATUS_IS_OK(status)) {
3807 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3808 fsp->fsp_name, nt_errstr(status) ));
3809 reply_nterror(req, status);
3810 END_PROFILE(SMBwrite);
3814 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3815 reply_unixerror(req, ERRHRD, ERRdiskfull);
3816 END_PROFILE(SMBwrite);
3820 reply_outbuf(req, 1, 0);
3822 SSVAL(req->outbuf,smb_vwv0,nwritten);
3824 if (nwritten < (ssize_t)numtowrite) {
3825 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3826 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3829 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3831 END_PROFILE(SMBwrite);
3835 /****************************************************************************
3836 Ensure a buffer is a valid writeX for recvfile purposes.
3837 ****************************************************************************/
3839 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3840 (2*14) + /* word count (including bcc) */ \
3843 bool is_valid_writeX_buffer(const uint8_t *inbuf)
3846 connection_struct *conn = NULL;
3847 unsigned int doff = 0;
3848 size_t len = smb_len_large(inbuf);
3850 if (is_encrypted_packet(inbuf)) {
3851 /* Can't do this on encrypted
3856 if (CVAL(inbuf,smb_com) != SMBwriteX) {
3860 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
3861 CVAL(inbuf,smb_wct) != 14) {
3862 DEBUG(10,("is_valid_writeX_buffer: chained or "
3863 "invalid word length.\n"));
3867 conn = conn_find(SVAL(inbuf, smb_tid));
3869 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
3873 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
3876 if (IS_PRINT(conn)) {
3877 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
3880 doff = SVAL(inbuf,smb_vwv11);
3882 numtowrite = SVAL(inbuf,smb_vwv10);
3884 if (len > doff && len - doff > 0xFFFF) {
3885 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
3888 if (numtowrite == 0) {
3889 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
3893 /* Ensure the sizes match up. */
3894 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
3895 /* no pad byte...old smbclient :-( */
3896 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
3898 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
3902 if (len - doff != numtowrite) {
3903 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
3904 "len = %u, doff = %u, numtowrite = %u\n",
3907 (unsigned int)numtowrite ));
3911 DEBUG(10,("is_valid_writeX_buffer: true "
3912 "len = %u, doff = %u, numtowrite = %u\n",
3915 (unsigned int)numtowrite ));
3920 /****************************************************************************
3921 Reply to a write and X.
3922 ****************************************************************************/
3924 void reply_write_and_X(struct smb_request *req)
3926 connection_struct *conn = req->conn;
3932 unsigned int smb_doff;
3933 unsigned int smblen;
3937 START_PROFILE(SMBwriteX);
3939 if ((req->wct != 12) && (req->wct != 14)) {
3940 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3941 END_PROFILE(SMBwriteX);
3945 numtowrite = SVAL(req->vwv+10, 0);
3946 smb_doff = SVAL(req->vwv+11, 0);
3947 smblen = smb_len(req->inbuf);
3949 if (req->unread_bytes > 0xFFFF ||
3950 (smblen > smb_doff &&
3951 smblen - smb_doff > 0xFFFF)) {
3952 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
3955 if (req->unread_bytes) {
3956 /* Can't do a recvfile write on IPC$ */
3958 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3959 END_PROFILE(SMBwriteX);
3962 if (numtowrite != req->unread_bytes) {
3963 reply_doserror(req, ERRDOS, ERRbadmem);
3964 END_PROFILE(SMBwriteX);
3968 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
3969 smb_doff + numtowrite > smblen) {
3970 reply_doserror(req, ERRDOS, ERRbadmem);
3971 END_PROFILE(SMBwriteX);
3976 /* If it's an IPC, pass off the pipe handler. */
3978 if (req->unread_bytes) {
3979 reply_doserror(req, ERRDOS, ERRbadmem);
3980 END_PROFILE(SMBwriteX);
3983 reply_pipe_write_and_X(req);
3984 END_PROFILE(SMBwriteX);
3988 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3989 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3990 write_through = BITSETW(req->vwv+7,0);
3992 if (!check_fsp(conn, req, fsp)) {
3993 END_PROFILE(SMBwriteX);
3997 if (!CHECK_WRITE(fsp)) {
3998 reply_doserror(req, ERRDOS, ERRbadaccess);
3999 END_PROFILE(SMBwriteX);
4003 data = smb_base(req->inbuf) + smb_doff;
4005 if(req->wct == 14) {
4006 #ifdef LARGE_SMB_OFF_T
4008 * This is a large offset (64 bit) write.
4010 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4012 #else /* !LARGE_SMB_OFF_T */
4015 * Ensure we haven't been sent a >32 bit offset.
4018 if(IVAL(req->vwv+12, 0) != 0) {
4019 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4020 "used and we don't support 64 bit offsets.\n",
4021 (unsigned int)IVAL(req->vwv+12, 0) ));
4022 reply_doserror(req, ERRDOS, ERRbadaccess);
4023 END_PROFILE(SMBwriteX);
4027 #endif /* LARGE_SMB_OFF_T */
4030 if (is_locked(fsp,(uint32)req->smbpid,
4031 (uint64_t)numtowrite,
4032 (uint64_t)startpos, WRITE_LOCK)) {
4033 reply_doserror(req, ERRDOS, ERRlock);
4034 END_PROFILE(SMBwriteX);
4038 /* X/Open SMB protocol says that, unlike SMBwrite
4039 if the length is zero then NO truncation is
4040 done, just a write of zero. To truncate a file,
4043 if(numtowrite == 0) {
4047 if ((req->unread_bytes == 0) &&
4048 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4050 END_PROFILE(SMBwriteX);
4054 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4057 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4058 reply_unixerror(req, ERRHRD, ERRdiskfull);
4059 END_PROFILE(SMBwriteX);
4063 reply_outbuf(req, 6, 0);
4064 SSVAL(req->outbuf,smb_vwv2,nwritten);
4065 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4067 if (nwritten < (ssize_t)numtowrite) {
4068 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4069 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4072 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4073 fsp->fnum, (int)numtowrite, (int)nwritten));
4075 status = sync_file(conn, fsp, write_through);
4076 if (!NT_STATUS_IS_OK(status)) {
4077 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4078 fsp->fsp_name, nt_errstr(status) ));
4079 reply_nterror(req, status);
4080 END_PROFILE(SMBwriteX);
4084 END_PROFILE(SMBwriteX);
4089 /****************************************************************************
4091 ****************************************************************************/
4093 void reply_lseek(struct smb_request *req)
4095 connection_struct *conn = req->conn;
4101 START_PROFILE(SMBlseek);
4104 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4105 END_PROFILE(SMBlseek);
4109 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4111 if (!check_fsp(conn, req, fsp)) {
4115 flush_write_cache(fsp, SEEK_FLUSH);
4117 mode = SVAL(req->vwv+1, 0) & 3;
4118 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4119 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4128 res = fsp->fh->pos + startpos;
4139 if (umode == SEEK_END) {
4140 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4141 if(errno == EINVAL) {
4142 SMB_OFF_T current_pos = startpos;
4143 SMB_STRUCT_STAT sbuf;
4145 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4146 reply_unixerror(req, ERRDOS,
4148 END_PROFILE(SMBlseek);
4152 current_pos += sbuf.st_size;
4154 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4159 reply_unixerror(req, ERRDOS, ERRnoaccess);
4160 END_PROFILE(SMBlseek);
4167 reply_outbuf(req, 2, 0);
4168 SIVAL(req->outbuf,smb_vwv0,res);
4170 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4171 fsp->fnum, (double)startpos, (double)res, mode));
4173 END_PROFILE(SMBlseek);
4177 /****************************************************************************
4179 ****************************************************************************/
4181 void reply_flush(struct smb_request *req)
4183 connection_struct *conn = req->conn;
4187 START_PROFILE(SMBflush);
4190 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4194 fnum = SVAL(req->vwv+0, 0);
4195 fsp = file_fsp(req, fnum);
4197 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4202 file_sync_all(conn);
4204 NTSTATUS status = sync_file(conn, fsp, True);
4205 if (!NT_STATUS_IS_OK(status)) {
4206 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4207 fsp->fsp_name, nt_errstr(status) ));
4208 reply_nterror(req, status);
4209 END_PROFILE(SMBflush);
4214 reply_outbuf(req, 0, 0);
4216 DEBUG(3,("flush\n"));
4217 END_PROFILE(SMBflush);
4221 /****************************************************************************
4223 conn POINTER CAN BE NULL HERE !
4224 ****************************************************************************/
4226 void reply_exit(struct smb_request *req)
4228 START_PROFILE(SMBexit);
4230 file_close_pid(req->smbpid, req->vuid);
4232 reply_outbuf(req, 0, 0);
4234 DEBUG(3,("exit\n"));
4236 END_PROFILE(SMBexit);
4240 /****************************************************************************
4241 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4242 ****************************************************************************/
4244 void reply_close(struct smb_request *req)
4246 connection_struct *conn = req->conn;
4247 NTSTATUS status = NT_STATUS_OK;
4248 files_struct *fsp = NULL;
4249 START_PROFILE(SMBclose);
4252 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4253 END_PROFILE(SMBclose);
4257 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4260 * We can only use check_fsp if we know it's not a directory.
4263 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4264 reply_doserror(req, ERRDOS, ERRbadfid);
4265 END_PROFILE(SMBclose);
4269 if(fsp->is_directory) {
4271 * Special case - close NT SMB directory handle.
4273 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4274 status = close_file(req, fsp, NORMAL_CLOSE);
4278 * Close ordinary file.
4281 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4282 fsp->fh->fd, fsp->fnum,
4283 conn->num_files_open));
4286 * Take care of any time sent in the close.
4289 t = srv_make_unix_date3(req->vwv+1);
4290 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4293 * close_file() returns the unix errno if an error
4294 * was detected on close - normally this is due to
4295 * a disk full error. If not then it was probably an I/O error.
4298 status = close_file(req, fsp, NORMAL_CLOSE);
4301 if (!NT_STATUS_IS_OK(status)) {
4302 reply_nterror(req, status);
4303 END_PROFILE(SMBclose);
4307 reply_outbuf(req, 0, 0);
4308 END_PROFILE(SMBclose);
4312 /****************************************************************************
4313 Reply to a writeclose (Core+ protocol).
4314 ****************************************************************************/
4316 void reply_writeclose(struct smb_request *req)
4318 connection_struct *conn = req->conn;
4320 ssize_t nwritten = -1;
4321 NTSTATUS close_status = NT_STATUS_OK;
4324 struct timespec mtime;
4327 START_PROFILE(SMBwriteclose);
4330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4331 END_PROFILE(SMBwriteclose);
4335 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4337 if (!check_fsp(conn, req, fsp)) {
4338 END_PROFILE(SMBwriteclose);
4341 if (!CHECK_WRITE(fsp)) {
4342 reply_doserror(req, ERRDOS,ERRbadaccess);
4343 END_PROFILE(SMBwriteclose);
4347 numtowrite = SVAL(req->vwv+1, 0);
4348 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4349 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4350 data = (const char *)req->buf + 1;
4353 && is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
4354 (uint64_t)startpos, WRITE_LOCK)) {
4355 reply_doserror(req, ERRDOS,ERRlock);
4356 END_PROFILE(SMBwriteclose);
4360 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4362 set_close_write_time(fsp, mtime);
4365 * More insanity. W2K only closes the file if writelen > 0.
4370 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4372 close_status = close_file(req, fsp, NORMAL_CLOSE);
4375 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4376 fsp->fnum, (int)numtowrite, (int)nwritten,
4377 conn->num_files_open));
4379 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4380 reply_doserror(req, ERRHRD, ERRdiskfull);
4381 END_PROFILE(SMBwriteclose);
4385 if(!NT_STATUS_IS_OK(close_status)) {
4386 reply_nterror(req, close_status);
4387 END_PROFILE(SMBwriteclose);
4391 reply_outbuf(req, 1, 0);
4393 SSVAL(req->outbuf,smb_vwv0,nwritten);
4394 END_PROFILE(SMBwriteclose);
4399 #define DBGC_CLASS DBGC_LOCKING
4401 /****************************************************************************
4403 ****************************************************************************/
4405 void reply_lock(struct smb_request *req)
4407 connection_struct *conn = req->conn;
4408 uint64_t count,offset;
4411 struct byte_range_lock *br_lck = NULL;
4413 START_PROFILE(SMBlock);
4416 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4417 END_PROFILE(SMBlock);
4421 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4423 if (!check_fsp(conn, req, fsp)) {
4424 END_PROFILE(SMBlock);
4428 release_level_2_oplocks_on_change(fsp);
4430 count = (uint64_t)IVAL(req->vwv+1, 0);
4431 offset = (uint64_t)IVAL(req->vwv+3, 0);
4433 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4434 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4436 br_lck = do_lock(smbd_messaging_context(),
4443 False, /* Non-blocking lock. */
4447 TALLOC_FREE(br_lck);
4449 if (NT_STATUS_V(status)) {
4450 reply_nterror(req, status);
4451 END_PROFILE(SMBlock);
4455 reply_outbuf(req, 0, 0);
4457 END_PROFILE(SMBlock);
4461 /****************************************************************************
4463 ****************************************************************************/
4465 void reply_unlock(struct smb_request *req)
4467 connection_struct *conn = req->conn;
4468 uint64_t count,offset;
4472 START_PROFILE(SMBunlock);
4475 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4476 END_PROFILE(SMBunlock);
4480 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4482 if (!check_fsp(conn, req, fsp)) {
4483 END_PROFILE(SMBunlock);
4487 count = (uint64_t)IVAL(req->vwv+1, 0);
4488 offset = (uint64_t)IVAL(req->vwv+3, 0);
4490 status = do_unlock(smbd_messaging_context(),
4497 if (NT_STATUS_V(status)) {
4498 reply_nterror(req, status);
4499 END_PROFILE(SMBunlock);
4503 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4504 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4506 reply_outbuf(req, 0, 0);
4508 END_PROFILE(SMBunlock);
4513 #define DBGC_CLASS DBGC_ALL
4515 /****************************************************************************
4517 conn POINTER CAN BE NULL HERE !
4518 ****************************************************************************/
4520 void reply_tdis(struct smb_request *req)
4522 connection_struct *conn = req->conn;
4523 START_PROFILE(SMBtdis);
4526 DEBUG(4,("Invalid connection in tdis\n"));
4527 reply_doserror(req, ERRSRV, ERRinvnid);
4528 END_PROFILE(SMBtdis);
4534 close_cnum(conn,req->vuid);
4537 reply_outbuf(req, 0, 0);
4538 END_PROFILE(SMBtdis);
4542 /****************************************************************************
4544 conn POINTER CAN BE NULL HERE !
4545 ****************************************************************************/
4547 void reply_echo(struct smb_request *req)
4549 connection_struct *conn = req->conn;
4553 START_PROFILE(SMBecho);
4556 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4557 END_PROFILE(SMBecho);
4561 smb_reverb = SVAL(req->vwv+0, 0);
4563 reply_outbuf(req, 1, req->buflen);
4565 /* copy any incoming data back out */
4566 if (req->buflen > 0) {
4567 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4570 if (smb_reverb > 100) {
4571 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4575 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
4576 SSVAL(req->outbuf,smb_vwv0,seq_num);
4578 show_msg((char *)req->outbuf);
4579 if (!srv_send_smb(smbd_server_fd(),
4580 (char *)req->outbuf,
4581 IS_CONN_ENCRYPTED(conn)||req->encrypted))
4582 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4585 DEBUG(3,("echo %d times\n", smb_reverb));
4587 TALLOC_FREE(req->outbuf);
4589 END_PROFILE(SMBecho);
4593 /****************************************************************************
4594 Reply to a printopen.
4595 ****************************************************************************/
4597 void reply_printopen(struct smb_request *req)
4599 connection_struct *conn = req->conn;
4601 SMB_STRUCT_STAT sbuf;
4604 START_PROFILE(SMBsplopen);
4607 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4608 END_PROFILE(SMBsplopen);
4612 if (!CAN_PRINT(conn)) {
4613 reply_doserror(req, ERRDOS, ERRnoaccess);
4614 END_PROFILE(SMBsplopen);
4618 status = file_new(req, conn, &fsp);
4619 if(!NT_STATUS_IS_OK(status)) {
4620 reply_nterror(req, status);
4621 END_PROFILE(SMBsplopen);
4625 /* Open for exclusive use, write only. */
4626 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4628 if (!NT_STATUS_IS_OK(status)) {
4629 reply_nterror(req, status);
4630 END_PROFILE(SMBsplopen);
4634 reply_outbuf(req, 1, 0);
4635 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4637 DEBUG(3,("openprint fd=%d fnum=%d\n",
4638 fsp->fh->fd, fsp->fnum));
4640 END_PROFILE(SMBsplopen);
4644 /****************************************************************************
4645 Reply to a printclose.
4646 ****************************************************************************/
4648 void reply_printclose(struct smb_request *req)
4650 connection_struct *conn = req->conn;
4654 START_PROFILE(SMBsplclose);
4657 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4658 END_PROFILE(SMBsplclose);
4662 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4664 if (!check_fsp(conn, req, fsp)) {
4665 END_PROFILE(SMBsplclose);
4669 if (!CAN_PRINT(conn)) {
4670 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4671 END_PROFILE(SMBsplclose);
4675 DEBUG(3,("printclose fd=%d fnum=%d\n",
4676 fsp->fh->fd,fsp->fnum));
4678 status = close_file(req, fsp, NORMAL_CLOSE);
4680 if(!NT_STATUS_IS_OK(status)) {
4681 reply_nterror(req, status);
4682 END_PROFILE(SMBsplclose);
4686 reply_outbuf(req, 0, 0);
4688 END_PROFILE(SMBsplclose);
4692 /****************************************************************************
4693 Reply to a printqueue.
4694 ****************************************************************************/
4696 void reply_printqueue(struct smb_request *req)
4698 connection_struct *conn = req->conn;
4702 START_PROFILE(SMBsplretq);
4705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4706 END_PROFILE(SMBsplretq);
4710 max_count = SVAL(req->vwv+0, 0);
4711 start_index = SVAL(req->vwv+1, 0);
4713 /* we used to allow the client to get the cnum wrong, but that
4714 is really quite gross and only worked when there was only
4715 one printer - I think we should now only accept it if they
4716 get it right (tridge) */
4717 if (!CAN_PRINT(conn)) {
4718 reply_doserror(req, ERRDOS, ERRnoaccess);
4719 END_PROFILE(SMBsplretq);
4723 reply_outbuf(req, 2, 3);
4724 SSVAL(req->outbuf,smb_vwv0,0);
4725 SSVAL(req->outbuf,smb_vwv1,0);
4726 SCVAL(smb_buf(req->outbuf),0,1);
4727 SSVAL(smb_buf(req->outbuf),1,0);
4729 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4730 start_index, max_count));
4733 print_queue_struct *queue = NULL;
4734 print_status_struct status;
4735 int count = print_queue_status(SNUM(conn), &queue, &status);
4736 int num_to_get = ABS(max_count);
4737 int first = (max_count>0?start_index:start_index+max_count+1);
4743 num_to_get = MIN(num_to_get,count-first);
4746 for (i=first;i<first+num_to_get;i++) {
4750 srv_put_dos_date2(p,0,queue[i].time);
4751 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4752 SSVAL(p,5, queue[i].job);
4753 SIVAL(p,7,queue[i].size);
4755 srvstr_push(blob, req->flags2, p+12,
4756 queue[i].fs_user, 16, STR_ASCII);
4758 if (message_push_blob(
4761 blob, sizeof(blob))) == -1) {
4762 reply_nterror(req, NT_STATUS_NO_MEMORY);
4763 END_PROFILE(SMBsplretq);
4769 SSVAL(req->outbuf,smb_vwv0,count);
4770 SSVAL(req->outbuf,smb_vwv1,
4771 (max_count>0?first+count:first-1));
4772 SCVAL(smb_buf(req->outbuf),0,1);
4773 SSVAL(smb_buf(req->outbuf),1,28*count);
4778 DEBUG(3,("%d entries returned in queue\n",count));
4781 END_PROFILE(SMBsplretq);
4785 /****************************************************************************
4786 Reply to a printwrite.
4787 ****************************************************************************/
4789 void reply_printwrite(struct smb_request *req)
4791 connection_struct *conn = req->conn;
4796 START_PROFILE(SMBsplwr);
4799 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4800 END_PROFILE(SMBsplwr);
4804 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4806 if (!check_fsp(conn, req, fsp)) {
4807 END_PROFILE(SMBsplwr);
4811 if (!CAN_PRINT(conn)) {
4812 reply_doserror(req, ERRDOS, ERRnoaccess);
4813 END_PROFILE(SMBsplwr);
4817 if (!CHECK_WRITE(fsp)) {
4818 reply_doserror(req, ERRDOS, ERRbadaccess);
4819 END_PROFILE(SMBsplwr);
4823 numtowrite = SVAL(req->buf, 1);
4825 if (req->buflen < numtowrite + 3) {
4826 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4827 END_PROFILE(SMBsplwr);
4831 data = (const char *)req->buf + 3;
4833 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
4834 reply_unixerror(req, ERRHRD, ERRdiskfull);
4835 END_PROFILE(SMBsplwr);
4839 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4841 END_PROFILE(SMBsplwr);
4845 /****************************************************************************
4847 ****************************************************************************/
4849 void reply_mkdir(struct smb_request *req)
4851 connection_struct *conn = req->conn;
4852 char *directory = NULL;
4854 SMB_STRUCT_STAT sbuf;
4855 TALLOC_CTX *ctx = talloc_tos();
4857 START_PROFILE(SMBmkdir);
4859 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
4860 STR_TERMINATE, &status);
4861 if (!NT_STATUS_IS_OK(status)) {
4862 reply_nterror(req, status);
4863 END_PROFILE(SMBmkdir);
4867 status = resolve_dfspath(ctx, conn,
4868 req->flags2 & FLAGS2_DFS_PATHNAMES,
4871 if (!NT_STATUS_IS_OK(status)) {
4872 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4873 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4874 ERRSRV, ERRbadpath);
4875 END_PROFILE(SMBmkdir);
4878 reply_nterror(req, status);
4879 END_PROFILE(SMBmkdir);
4883 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
4884 if (!NT_STATUS_IS_OK(status)) {
4885 reply_nterror(req, status);
4886 END_PROFILE(SMBmkdir);
4890 status = check_name(conn, directory);
4891 if (!NT_STATUS_IS_OK(status)) {
4892 reply_nterror(req, status);
4893 END_PROFILE(SMBmkdir);
4897 status = create_directory(conn, req, directory);
4899 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4901 if (!NT_STATUS_IS_OK(status)) {
4903 if (!use_nt_status()
4904 && NT_STATUS_EQUAL(status,
4905 NT_STATUS_OBJECT_NAME_COLLISION)) {
4907 * Yes, in the DOS error code case we get a
4908 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4909 * samba4 torture test.
4911 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4914 reply_nterror(req, status);
4915 END_PROFILE(SMBmkdir);
4919 reply_outbuf(req, 0, 0);
4921 DEBUG( 3, ( "mkdir %s\n", directory ) );
4923 END_PROFILE(SMBmkdir);
4927 /****************************************************************************
4928 Static function used by reply_rmdir to delete an entire directory
4929 tree recursively. Return True on ok, False on fail.
4930 ****************************************************************************/
4932 static bool recursive_rmdir(TALLOC_CTX *ctx,
4933 connection_struct *conn,
4936 const char *dname = NULL;
4939 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
4945 while((dname = ReadDirName(dir_hnd, &offset))) {
4946 char *fullname = NULL;
4949 if (ISDOT(dname) || ISDOTDOT(dname)) {
4953 if (!is_visible_file(conn, directory, dname, &st, False)) {
4957 /* Construct the full name. */
4958 fullname = talloc_asprintf(ctx,
4968 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4973 if(st.st_mode & S_IFDIR) {
4974 if(!recursive_rmdir(ctx, conn, fullname)) {
4978 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4982 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4986 TALLOC_FREE(fullname);
4988 TALLOC_FREE(dir_hnd);
4992 /****************************************************************************
4993 The internals of the rmdir code - called elsewhere.
4994 ****************************************************************************/
4996 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
4997 connection_struct *conn,
4998 const char *directory)
5003 /* Might be a symlink. */
5004 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5005 return map_nt_error_from_unix(errno);
5008 if (S_ISLNK(st.st_mode)) {
5009 /* Is what it points to a directory ? */
5010 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5011 return map_nt_error_from_unix(errno);
5013 if (!(S_ISDIR(st.st_mode))) {
5014 return NT_STATUS_NOT_A_DIRECTORY;
5016 ret = SMB_VFS_UNLINK(conn,directory);
5018 ret = SMB_VFS_RMDIR(conn,directory);
5021 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5022 FILE_NOTIFY_CHANGE_DIR_NAME,
5024 return NT_STATUS_OK;
5027 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5029 * Check to see if the only thing in this directory are
5030 * vetoed files/directories. If so then delete them and
5031 * retry. If we fail to delete any of them (and we *don't*
5032 * do a recursive delete) then fail the rmdir.
5036 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5037 directory, NULL, 0);
5039 if(dir_hnd == NULL) {
5044 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
5045 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5047 if (!is_visible_file(conn, directory, dname, &st, False))
5049 if(!IS_VETO_PATH(conn, dname)) {
5050 TALLOC_FREE(dir_hnd);
5056 /* We only have veto files/directories.
5057 * Are we allowed to delete them ? */
5059 if(!lp_recursive_veto_delete(SNUM(conn))) {
5060 TALLOC_FREE(dir_hnd);
5065 /* Do a recursive delete. */
5066 RewindDir(dir_hnd,&dirpos);
5067 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
5068 char *fullname = NULL;
5070 if (ISDOT(dname) || ISDOTDOT(dname)) {
5073 if (!is_visible_file(conn, directory, dname, &st, False)) {
5077 fullname = talloc_asprintf(ctx,
5087 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5090 if(st.st_mode & S_IFDIR) {
5091 if(!recursive_rmdir(ctx, conn, fullname)) {
5094 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5097 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5100 TALLOC_FREE(fullname);
5102 TALLOC_FREE(dir_hnd);
5103 /* Retry the rmdir */
5104 ret = SMB_VFS_RMDIR(conn,directory);
5110 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5111 "%s\n", directory,strerror(errno)));
5112 return map_nt_error_from_unix(errno);
5115 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5116 FILE_NOTIFY_CHANGE_DIR_NAME,
5119 return NT_STATUS_OK;
5122 /****************************************************************************
5124 ****************************************************************************/
5126 void reply_rmdir(struct smb_request *req)
5128 connection_struct *conn = req->conn;
5129 char *directory = NULL;
5130 SMB_STRUCT_STAT sbuf;
5132 TALLOC_CTX *ctx = talloc_tos();
5134 START_PROFILE(SMBrmdir);
5136 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5137 STR_TERMINATE, &status);
5138 if (!NT_STATUS_IS_OK(status)) {
5139 reply_nterror(req, status);
5140 END_PROFILE(SMBrmdir);
5144 status = resolve_dfspath(ctx, conn,
5145 req->flags2 & FLAGS2_DFS_PATHNAMES,
5148 if (!NT_STATUS_IS_OK(status)) {
5149 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5150 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5151 ERRSRV, ERRbadpath);
5152 END_PROFILE(SMBrmdir);
5155 reply_nterror(req, status);
5156 END_PROFILE(SMBrmdir);
5160 status = unix_convert(ctx, conn, directory, False, &directory,
5162 if (!NT_STATUS_IS_OK(status)) {
5163 reply_nterror(req, status);
5164 END_PROFILE(SMBrmdir);
5168 status = check_name(conn, directory);
5169 if (!NT_STATUS_IS_OK(status)) {
5170 reply_nterror(req, status);
5171 END_PROFILE(SMBrmdir);
5175 dptr_closepath(directory, req->smbpid);
5176 status = rmdir_internals(ctx, conn, directory);
5177 if (!NT_STATUS_IS_OK(status)) {
5178 reply_nterror(req, status);
5179 END_PROFILE(SMBrmdir);
5183 reply_outbuf(req, 0, 0);
5185 DEBUG( 3, ( "rmdir %s\n", directory ) );
5187 END_PROFILE(SMBrmdir);
5191 /*******************************************************************
5192 Resolve wildcards in a filename rename.
5193 ********************************************************************/
5195 static bool resolve_wildcards(TALLOC_CTX *ctx,
5200 char *name2_copy = NULL;
5205 char *p,*p2, *pname1, *pname2;
5207 name2_copy = talloc_strdup(ctx, name2);
5212 pname1 = strrchr_m(name1,'/');
5213 pname2 = strrchr_m(name2_copy,'/');
5215 if (!pname1 || !pname2) {
5219 /* Truncate the copy of name2 at the last '/' */
5222 /* Now go past the '/' */
5226 root1 = talloc_strdup(ctx, pname1);
5227 root2 = talloc_strdup(ctx, pname2);
5229 if (!root1 || !root2) {
5233 p = strrchr_m(root1,'.');
5236 ext1 = talloc_strdup(ctx, p+1);
5238 ext1 = talloc_strdup(ctx, "");
5240 p = strrchr_m(root2,'.');
5243 ext2 = talloc_strdup(ctx, p+1);
5245 ext2 = talloc_strdup(ctx, "");
5248 if (!ext1 || !ext2) {
5256 /* Hmmm. Should this be mb-aware ? */
5259 } else if (*p2 == '*') {
5261 root2 = talloc_asprintf(ctx, "%s%s",
5280 /* Hmmm. Should this be mb-aware ? */
5283 } else if (*p2 == '*') {
5285 ext2 = talloc_asprintf(ctx, "%s%s",
5301 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5306 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5318 /****************************************************************************
5319 Ensure open files have their names updated. Updated to notify other smbd's
5321 ****************************************************************************/
5323 static void rename_open_files(connection_struct *conn,
5324 struct share_mode_lock *lck,
5325 const char *newname)
5328 bool did_rename = False;
5330 for(fsp = file_find_di_first(lck->id); fsp;
5331 fsp = file_find_di_next(fsp)) {
5332 /* fsp_name is a relative path under the fsp. To change this for other
5333 sharepaths we need to manipulate relative paths. */
5334 /* TODO - create the absolute path and manipulate the newname
5335 relative to the sharepath. */
5336 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5339 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5340 fsp->fnum, file_id_string_tos(&fsp->file_id),
5341 fsp->fsp_name, newname ));
5342 string_set(&fsp->fsp_name, newname);
5347 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5348 file_id_string_tos(&lck->id), newname ));
5351 /* Send messages to all smbd's (not ourself) that the name has changed. */
5352 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5356 /****************************************************************************
5357 We need to check if the source path is a parent directory of the destination
5358 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5359 refuse the rename with a sharing violation. Under UNIX the above call can
5360 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5361 probably need to check that the client is a Windows one before disallowing
5362 this as a UNIX client (one with UNIX extensions) can know the source is a
5363 symlink and make this decision intelligently. Found by an excellent bug
5364 report from <AndyLiebman@aol.com>.
5365 ****************************************************************************/
5367 static bool rename_path_prefix_equal(const char *src, const char *dest)
5369 const char *psrc = src;
5370 const char *pdst = dest;
5373 if (psrc[0] == '.' && psrc[1] == '/') {
5376 if (pdst[0] == '.' && pdst[1] == '/') {
5379 if ((slen = strlen(psrc)) > strlen(pdst)) {
5382 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5386 * Do the notify calls from a rename
5389 static void notify_rename(connection_struct *conn, bool is_dir,
5390 const char *oldpath, const char *newpath)
5392 char *olddir, *newdir;
5393 const char *oldname, *newname;
5396 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5397 : FILE_NOTIFY_CHANGE_FILE_NAME;
5399 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5400 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5401 TALLOC_FREE(olddir);
5405 if (strcmp(olddir, newdir) == 0) {
5406 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5407 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5410 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5411 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5413 TALLOC_FREE(olddir);
5414 TALLOC_FREE(newdir);
5416 /* this is a strange one. w2k3 gives an additional event for
5417 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5418 files, but not directories */
5420 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5421 FILE_NOTIFY_CHANGE_ATTRIBUTES
5422 |FILE_NOTIFY_CHANGE_CREATION,
5427 /****************************************************************************
5428 Rename an open file - given an fsp.
5429 ****************************************************************************/
5431 NTSTATUS rename_internals_fsp(connection_struct *conn,
5434 const char *newname_last_component,
5436 bool replace_if_exists)
5438 TALLOC_CTX *ctx = talloc_tos();
5439 SMB_STRUCT_STAT sbuf, sbuf1;
5440 NTSTATUS status = NT_STATUS_OK;
5441 struct share_mode_lock *lck = NULL;
5442 bool dst_exists, old_is_stream, new_is_stream;
5446 status = check_name(conn, newname);
5447 if (!NT_STATUS_IS_OK(status)) {
5451 /* Ensure newname contains a '/' */
5452 if(strrchr_m(newname,'/') == 0) {
5453 newname = talloc_asprintf(ctx,
5457 return NT_STATUS_NO_MEMORY;
5462 * Check for special case with case preserving and not
5463 * case sensitive. If the old last component differs from the original
5464 * last component only by case, then we should allow
5465 * the rename (user is trying to change the case of the
5469 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5470 strequal(newname, fsp->fsp_name)) {
5472 char *newname_modified_last_component = NULL;
5475 * Get the last component of the modified name.
5476 * Note that we guarantee that newname contains a '/'
5479 p = strrchr_m(newname,'/');
5480 newname_modified_last_component = talloc_strdup(ctx,
5482 if (!newname_modified_last_component) {
5483 return NT_STATUS_NO_MEMORY;
5486 if(strcsequal(newname_modified_last_component,
5487 newname_last_component) == False) {
5489 * Replace the modified last component with
5492 *p = '\0'; /* Truncate at the '/' */
5493 newname = talloc_asprintf(ctx,
5496 newname_last_component);
5501 * If the src and dest names are identical - including case,
5502 * don't do the rename, just return success.
5505 if (strcsequal(fsp->fsp_name, newname)) {
5506 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5508 return NT_STATUS_OK;
5511 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5512 new_is_stream = is_ntfs_stream_name(newname);
5514 /* Return the correct error code if both names aren't streams. */
5515 if (!old_is_stream && new_is_stream) {
5516 return NT_STATUS_OBJECT_NAME_INVALID;
5519 if (old_is_stream && !new_is_stream) {
5520 return NT_STATUS_INVALID_PARAMETER;
5524 * Have vfs_object_exist also fill sbuf1
5526 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5528 if(!replace_if_exists && dst_exists) {
5529 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5530 fsp->fsp_name,newname));
5531 return NT_STATUS_OBJECT_NAME_COLLISION;
5535 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5536 files_struct *dst_fsp = file_find_di_first(fileid);
5537 /* The file can be open when renaming a stream */
5538 if (dst_fsp && !new_is_stream) {
5539 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5540 return NT_STATUS_ACCESS_DENIED;
5544 /* Ensure we have a valid stat struct for the source. */
5545 if (fsp->fh->fd != -1) {
5546 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5547 return map_nt_error_from_unix(errno);
5550 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
5551 return map_nt_error_from_unix(errno);
5555 status = can_rename(conn, fsp, attrs, &sbuf);
5557 if (!NT_STATUS_IS_OK(status)) {
5558 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5559 nt_errstr(status), fsp->fsp_name,newname));
5560 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5561 status = NT_STATUS_ACCESS_DENIED;
5565 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5566 return NT_STATUS_ACCESS_DENIED;
5569 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5573 * We have the file open ourselves, so not being able to get the
5574 * corresponding share mode lock is a fatal error.
5577 SMB_ASSERT(lck != NULL);
5579 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5580 uint32 create_options = fsp->fh->private_options;
5582 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5583 fsp->fsp_name,newname));
5585 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5587 rename_open_files(conn, lck, newname);
5590 * A rename acts as a new file create w.r.t. allowing an initial delete
5591 * on close, probably because in Windows there is a new handle to the
5592 * new file. If initial delete on close was requested but not
5593 * originally set, we need to set it here. This is probably not 100% correct,
5594 * but will work for the CIFSFS client which in non-posix mode
5595 * depends on these semantics. JRA.
5598 if (create_options & FILE_DELETE_ON_CLOSE) {
5599 status = can_set_delete_on_close(fsp, True, 0);
5601 if (NT_STATUS_IS_OK(status)) {
5602 /* Note that here we set the *inital* delete on close flag,
5603 * not the regular one. The magic gets handled in close. */
5604 fsp->initial_delete_on_close = True;
5608 return NT_STATUS_OK;
5613 if (errno == ENOTDIR || errno == EISDIR) {
5614 status = NT_STATUS_OBJECT_NAME_COLLISION;
5616 status = map_nt_error_from_unix(errno);
5619 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5620 nt_errstr(status), fsp->fsp_name,newname));
5625 /****************************************************************************
5626 The guts of the rename command, split out so it may be called by the NT SMB
5628 ****************************************************************************/
5630 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5631 connection_struct *conn,
5632 struct smb_request *req,
5633 const char *name_in,
5634 const char *newname_in,
5636 bool replace_if_exists,
5639 uint32_t access_mask)
5641 char *directory = NULL;
5643 char *last_component_src = NULL;
5644 char *last_component_dest = NULL;
5646 char *newname = NULL;
5649 NTSTATUS status = NT_STATUS_OK;
5650 SMB_STRUCT_STAT sbuf1, sbuf2;
5651 struct smb_Dir *dir_hnd = NULL;
5654 int create_options = 0;
5659 status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5660 &last_component_src, &sbuf1);
5661 if (!NT_STATUS_IS_OK(status)) {
5665 status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5666 &last_component_dest, &sbuf2);
5667 if (!NT_STATUS_IS_OK(status)) {
5672 * Split the old name into directory and last component
5673 * strings. Note that unix_convert may have stripped off a
5674 * leading ./ from both name and newname if the rename is
5675 * at the root of the share. We need to make sure either both
5676 * name and newname contain a / character or neither of them do
5677 * as this is checked in resolve_wildcards().
5680 p = strrchr_m(name,'/');
5682 directory = talloc_strdup(ctx, ".");
5684 return NT_STATUS_NO_MEMORY;
5689 directory = talloc_strdup(ctx, name);
5691 return NT_STATUS_NO_MEMORY;
5694 *p = '/'; /* Replace needed for exceptional test below. */
5698 * We should only check the mangled cache
5699 * here if unix_convert failed. This means
5700 * that the path in 'mask' doesn't exist
5701 * on the file system and so we need to look
5702 * for a possible mangle. This patch from
5703 * Tine Smukavec <valentin.smukavec@hermes.si>.
5706 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5707 char *new_mask = NULL;
5708 mangle_lookup_name_from_8_3(ctx,
5717 if (!src_has_wild) {
5721 * No wildcards - just process the one file.
5723 bool is_short_name = mangle_is_8_3(name, True, conn->params);
5725 /* Add a terminating '/' to the directory name. */
5726 directory = talloc_asprintf_append(directory,
5730 return NT_STATUS_NO_MEMORY;
5733 /* Ensure newname contains a '/' also */
5734 if(strrchr_m(newname,'/') == 0) {
5735 newname = talloc_asprintf(ctx,
5739 return NT_STATUS_NO_MEMORY;
5743 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5744 "case_preserve = %d, short case preserve = %d, "
5745 "directory = %s, newname = %s, "
5746 "last_component_dest = %s, is_8_3 = %d\n",
5747 conn->case_sensitive, conn->case_preserve,
5748 conn->short_case_preserve, directory,
5749 newname, last_component_dest, is_short_name));
5751 /* The dest name still may have wildcards. */
5752 if (dest_has_wild) {
5753 char *mod_newname = NULL;
5754 if (!resolve_wildcards(ctx,
5755 directory,newname,&mod_newname)) {
5756 DEBUG(6, ("rename_internals: resolve_wildcards "
5760 return NT_STATUS_NO_MEMORY;
5762 newname = mod_newname;
5766 SMB_VFS_STAT(conn, directory, &sbuf1);
5768 if (S_ISDIR(sbuf1.st_mode)) {
5769 create_options |= FILE_DIRECTORY_FILE;
5772 status = SMB_VFS_CREATE_FILE(
5775 0, /* root_dir_fid */
5776 directory, /* fname */
5777 0, /* create_file_flags */
5778 access_mask, /* access_mask */
5779 (FILE_SHARE_READ | /* share_access */
5781 FILE_OPEN, /* create_disposition*/
5782 create_options, /* create_options */
5783 0, /* file_attributes */
5784 0, /* oplock_request */
5785 0, /* allocation_size */
5790 &sbuf1); /* psbuf */
5792 if (!NT_STATUS_IS_OK(status)) {
5793 DEBUG(3, ("Could not open rename source %s: %s\n",
5794 directory, nt_errstr(status)));
5798 status = rename_internals_fsp(conn, fsp, newname,
5799 last_component_dest,
5800 attrs, replace_if_exists);
5802 close_file(req, fsp, NORMAL_CLOSE);
5804 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5805 nt_errstr(status), directory,newname));
5811 * Wildcards - process each file that matches.
5813 if (strequal(mask,"????????.???")) {
5818 status = check_name(conn, directory);
5819 if (!NT_STATUS_IS_OK(status)) {
5823 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
5824 if (dir_hnd == NULL) {
5825 return map_nt_error_from_unix(errno);
5828 status = NT_STATUS_NO_SUCH_FILE;
5830 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5831 * - gentest fix. JRA
5834 while ((dname = ReadDirName(dir_hnd, &offset))) {
5835 files_struct *fsp = NULL;
5837 char *destname = NULL;
5838 bool sysdir_entry = False;
5840 /* Quick check for "." and ".." */
5841 if (ISDOT(dname) || ISDOTDOT(dname)) {
5843 sysdir_entry = True;
5849 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5853 if(!mask_match(dname, mask, conn->case_sensitive)) {
5858 status = NT_STATUS_OBJECT_NAME_INVALID;
5862 fname = talloc_asprintf(ctx,
5867 return NT_STATUS_NO_MEMORY;
5870 if (!resolve_wildcards(ctx,
5871 fname,newname,&destname)) {
5872 DEBUG(6, ("resolve_wildcards %s %s failed\n",
5878 return NT_STATUS_NO_MEMORY;
5882 SMB_VFS_STAT(conn, fname, &sbuf1);
5886 if (S_ISDIR(sbuf1.st_mode)) {
5887 create_options |= FILE_DIRECTORY_FILE;
5890 status = SMB_VFS_CREATE_FILE(
5893 0, /* root_dir_fid */
5895 0, /* create_file_flags */
5896 access_mask, /* access_mask */
5897 (FILE_SHARE_READ | /* share_access */
5899 FILE_OPEN, /* create_disposition*/
5900 create_options, /* create_options */
5901 0, /* file_attributes */
5902 0, /* oplock_request */
5903 0, /* allocation_size */
5908 &sbuf1); /* psbuf */
5910 if (!NT_STATUS_IS_OK(status)) {
5911 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
5912 "returned %s rename %s -> %s\n",
5913 nt_errstr(status), directory, newname));
5917 status = rename_internals_fsp(conn, fsp, destname, dname,
5918 attrs, replace_if_exists);
5920 close_file(req, fsp, NORMAL_CLOSE);
5922 if (!NT_STATUS_IS_OK(status)) {
5923 DEBUG(3, ("rename_internals_fsp returned %s for "
5924 "rename %s -> %s\n", nt_errstr(status),
5925 directory, newname));
5931 DEBUG(3,("rename_internals: doing rename on %s -> "
5932 "%s\n",fname,destname));
5935 TALLOC_FREE(destname);
5937 TALLOC_FREE(dir_hnd);
5939 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
5940 status = map_nt_error_from_unix(errno);
5946 /****************************************************************************
5948 ****************************************************************************/
5950 void reply_mv(struct smb_request *req)
5952 connection_struct *conn = req->conn;
5954 char *newname = NULL;
5958 bool src_has_wcard = False;
5959 bool dest_has_wcard = False;
5960 TALLOC_CTX *ctx = talloc_tos();
5962 START_PROFILE(SMBmv);
5965 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5970 attrs = SVAL(req->vwv+0, 0);
5972 p = (const char *)req->buf + 1;
5973 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
5974 &status, &src_has_wcard);
5975 if (!NT_STATUS_IS_OK(status)) {
5976 reply_nterror(req, status);
5981 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
5982 &status, &dest_has_wcard);
5983 if (!NT_STATUS_IS_OK(status)) {
5984 reply_nterror(req, status);
5989 status = resolve_dfspath_wcard(ctx, conn,
5990 req->flags2 & FLAGS2_DFS_PATHNAMES,
5994 if (!NT_STATUS_IS_OK(status)) {
5995 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5996 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5997 ERRSRV, ERRbadpath);
6001 reply_nterror(req, status);
6006 status = resolve_dfspath_wcard(ctx, conn,
6007 req->flags2 & FLAGS2_DFS_PATHNAMES,
6011 if (!NT_STATUS_IS_OK(status)) {
6012 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6013 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6014 ERRSRV, ERRbadpath);
6018 reply_nterror(req, status);
6023 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6025 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6026 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6027 if (!NT_STATUS_IS_OK(status)) {
6028 if (open_was_deferred(req->mid)) {
6029 /* We have re-scheduled this call. */
6033 reply_nterror(req, status);
6038 reply_outbuf(req, 0, 0);
6044 /*******************************************************************
6045 Copy a file as part of a reply_copy.
6046 ******************************************************************/
6049 * TODO: check error codes on all callers
6052 NTSTATUS copy_file(TALLOC_CTX *ctx,
6053 connection_struct *conn,
6058 bool target_is_directory)
6060 SMB_STRUCT_STAT src_sbuf, sbuf2;
6062 files_struct *fsp1,*fsp2;
6065 uint32 new_create_disposition;
6068 dest = talloc_strdup(ctx, dest1);
6070 return NT_STATUS_NO_MEMORY;
6072 if (target_is_directory) {
6073 const char *p = strrchr_m(src,'/');
6079 dest = talloc_asprintf_append(dest,
6083 return NT_STATUS_NO_MEMORY;
6087 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6089 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6092 if (!target_is_directory && count) {
6093 new_create_disposition = FILE_OPEN;
6095 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6096 NULL, NULL, &new_create_disposition, NULL)) {
6098 return NT_STATUS_INVALID_PARAMETER;
6102 status = SMB_VFS_CREATE_FILE(
6105 0, /* root_dir_fid */
6107 0, /* create_file_flags */
6108 FILE_GENERIC_READ, /* access_mask */
6109 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6110 FILE_OPEN, /* create_disposition*/
6111 0, /* create_options */
6112 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6113 INTERNAL_OPEN_ONLY, /* oplock_request */
6114 0, /* allocation_size */
6119 &src_sbuf); /* psbuf */
6121 if (!NT_STATUS_IS_OK(status)) {
6126 dosattrs = dos_mode(conn, src, &src_sbuf);
6127 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6128 ZERO_STRUCTP(&sbuf2);
6131 status = SMB_VFS_CREATE_FILE(
6134 0, /* root_dir_fid */
6136 0, /* create_file_flags */
6137 FILE_GENERIC_WRITE, /* access_mask */
6138 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6139 new_create_disposition, /* create_disposition*/
6140 0, /* create_options */
6141 dosattrs, /* file_attributes */
6142 INTERNAL_OPEN_ONLY, /* oplock_request */
6143 0, /* allocation_size */
6148 &sbuf2); /* psbuf */
6152 if (!NT_STATUS_IS_OK(status)) {
6153 close_file(NULL, fsp1, ERROR_CLOSE);
6157 if ((ofun&3) == 1) {
6158 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6159 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6161 * Stop the copy from occurring.
6164 src_sbuf.st_size = 0;
6168 if (src_sbuf.st_size) {
6169 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6172 close_file(NULL, fsp1, NORMAL_CLOSE);
6174 /* Ensure the modtime is set correctly on the destination file. */
6175 set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
6178 * As we are opening fsp1 read-only we only expect
6179 * an error on close on fsp2 if we are out of space.
6180 * Thus we don't look at the error return from the
6183 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6185 if (!NT_STATUS_IS_OK(status)) {
6189 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6190 return NT_STATUS_DISK_FULL;
6193 return NT_STATUS_OK;
6196 /****************************************************************************
6197 Reply to a file copy.
6198 ****************************************************************************/
6200 void reply_copy(struct smb_request *req)
6202 connection_struct *conn = req->conn;
6204 char *newname = NULL;
6205 char *directory = NULL;
6206 const char *mask = NULL;
6207 const char mask_star[] = "*";
6210 int error = ERRnoaccess;
6215 bool target_is_directory=False;
6216 bool source_has_wild = False;
6217 bool dest_has_wild = False;
6218 SMB_STRUCT_STAT sbuf1, sbuf2;
6220 TALLOC_CTX *ctx = talloc_tos();
6222 START_PROFILE(SMBcopy);
6225 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6226 END_PROFILE(SMBcopy);
6230 tid2 = SVAL(req->vwv+0, 0);
6231 ofun = SVAL(req->vwv+1, 0);
6232 flags = SVAL(req->vwv+2, 0);
6234 p = (const char *)req->buf;
6235 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6236 &status, &source_has_wild);
6237 if (!NT_STATUS_IS_OK(status)) {
6238 reply_nterror(req, status);
6239 END_PROFILE(SMBcopy);
6242 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6243 &status, &dest_has_wild);
6244 if (!NT_STATUS_IS_OK(status)) {
6245 reply_nterror(req, status);
6246 END_PROFILE(SMBcopy);
6250 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6252 if (tid2 != conn->cnum) {
6253 /* can't currently handle inter share copies XXXX */
6254 DEBUG(3,("Rejecting inter-share copy\n"));
6255 reply_doserror(req, ERRSRV, ERRinvdevice);
6256 END_PROFILE(SMBcopy);
6260 status = resolve_dfspath_wcard(ctx, conn,
6261 req->flags2 & FLAGS2_DFS_PATHNAMES,
6265 if (!NT_STATUS_IS_OK(status)) {
6266 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6267 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6268 ERRSRV, ERRbadpath);
6269 END_PROFILE(SMBcopy);
6272 reply_nterror(req, status);
6273 END_PROFILE(SMBcopy);
6277 status = resolve_dfspath_wcard(ctx, conn,
6278 req->flags2 & FLAGS2_DFS_PATHNAMES,
6282 if (!NT_STATUS_IS_OK(status)) {
6283 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6284 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6285 ERRSRV, ERRbadpath);
6286 END_PROFILE(SMBcopy);
6289 reply_nterror(req, status);
6290 END_PROFILE(SMBcopy);
6294 status = unix_convert(ctx, conn, name, source_has_wild,
6295 &name, NULL, &sbuf1);
6296 if (!NT_STATUS_IS_OK(status)) {
6297 reply_nterror(req, status);
6298 END_PROFILE(SMBcopy);
6302 status = unix_convert(ctx, conn, newname, dest_has_wild,
6303 &newname, NULL, &sbuf2);
6304 if (!NT_STATUS_IS_OK(status)) {
6305 reply_nterror(req, status);
6306 END_PROFILE(SMBcopy);
6310 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6312 if ((flags&1) && target_is_directory) {
6313 reply_doserror(req, ERRDOS, ERRbadfile);
6314 END_PROFILE(SMBcopy);
6318 if ((flags&2) && !target_is_directory) {
6319 reply_doserror(req, ERRDOS, ERRbadpath);
6320 END_PROFILE(SMBcopy);
6324 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6325 /* wants a tree copy! XXXX */
6326 DEBUG(3,("Rejecting tree copy\n"));
6327 reply_doserror(req, ERRSRV, ERRerror);
6328 END_PROFILE(SMBcopy);
6332 p = strrchr_m(name,'/');
6334 directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
6337 directory = talloc_strdup(ctx, "./");
6342 reply_nterror(req, NT_STATUS_NO_MEMORY);
6343 END_PROFILE(SMBcopy);
6348 * We should only check the mangled cache
6349 * here if unix_convert failed. This means
6350 * that the path in 'mask' doesn't exist
6351 * on the file system and so we need to look
6352 * for a possible mangle. This patch from
6353 * Tine Smukavec <valentin.smukavec@hermes.si>.
6356 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6357 char *new_mask = NULL;
6358 mangle_lookup_name_from_8_3(ctx,
6367 if (!source_has_wild) {
6368 directory = talloc_asprintf_append(directory,
6371 if (dest_has_wild) {
6372 char *mod_newname = NULL;
6373 if (!resolve_wildcards(ctx,
6374 directory,newname,&mod_newname)) {
6375 reply_nterror(req, NT_STATUS_NO_MEMORY);
6376 END_PROFILE(SMBcopy);
6379 newname = mod_newname;
6382 status = check_name(conn, directory);
6383 if (!NT_STATUS_IS_OK(status)) {
6384 reply_nterror(req, status);
6385 END_PROFILE(SMBcopy);
6389 status = check_name(conn, newname);
6390 if (!NT_STATUS_IS_OK(status)) {
6391 reply_nterror(req, status);
6392 END_PROFILE(SMBcopy);
6396 status = copy_file(ctx,conn,directory,newname,ofun,
6397 count,target_is_directory);
6399 if(!NT_STATUS_IS_OK(status)) {
6400 reply_nterror(req, status);
6401 END_PROFILE(SMBcopy);
6407 struct smb_Dir *dir_hnd = NULL;
6408 const char *dname = NULL;
6411 if (strequal(mask,"????????.???")) {
6415 status = check_name(conn, directory);
6416 if (!NT_STATUS_IS_OK(status)) {
6417 reply_nterror(req, status);
6418 END_PROFILE(SMBcopy);
6422 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6423 if (dir_hnd == NULL) {
6424 status = map_nt_error_from_unix(errno);
6425 reply_nterror(req, status);
6426 END_PROFILE(SMBcopy);
6432 while ((dname = ReadDirName(dir_hnd, &offset))) {
6433 char *destname = NULL;
6436 if (ISDOT(dname) || ISDOTDOT(dname)) {
6440 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6444 if(!mask_match(dname, mask, conn->case_sensitive)) {
6448 error = ERRnoaccess;
6449 fname = talloc_asprintf(ctx,
6454 TALLOC_FREE(dir_hnd);
6455 reply_nterror(req, NT_STATUS_NO_MEMORY);
6456 END_PROFILE(SMBcopy);
6460 if (!resolve_wildcards(ctx,
6461 fname,newname,&destname)) {
6465 TALLOC_FREE(dir_hnd);
6466 reply_nterror(req, NT_STATUS_NO_MEMORY);
6467 END_PROFILE(SMBcopy);
6471 status = check_name(conn, fname);
6472 if (!NT_STATUS_IS_OK(status)) {
6473 TALLOC_FREE(dir_hnd);
6474 reply_nterror(req, status);
6475 END_PROFILE(SMBcopy);
6479 status = check_name(conn, destname);
6480 if (!NT_STATUS_IS_OK(status)) {
6481 TALLOC_FREE(dir_hnd);
6482 reply_nterror(req, status);
6483 END_PROFILE(SMBcopy);
6487 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6489 status = copy_file(ctx,conn,fname,destname,ofun,
6490 count,target_is_directory);
6491 if (NT_STATUS_IS_OK(status)) {
6495 TALLOC_FREE(destname);
6497 TALLOC_FREE(dir_hnd);
6502 /* Error on close... */
6504 reply_unixerror(req, ERRHRD, ERRgeneral);
6505 END_PROFILE(SMBcopy);
6509 reply_doserror(req, ERRDOS, error);
6510 END_PROFILE(SMBcopy);
6514 reply_outbuf(req, 1, 0);
6515 SSVAL(req->outbuf,smb_vwv0,count);
6517 END_PROFILE(SMBcopy);
6522 #define DBGC_CLASS DBGC_LOCKING
6524 /****************************************************************************
6525 Get a lock pid, dealing with large count requests.
6526 ****************************************************************************/
6528 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6529 bool large_file_format)
6531 if(!large_file_format)
6532 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6534 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6537 /****************************************************************************
6538 Get a lock count, dealing with large count requests.
6539 ****************************************************************************/
6541 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6542 bool large_file_format)
6546 if(!large_file_format) {
6547 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6550 #if defined(HAVE_LONGLONG)
6551 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6552 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6553 #else /* HAVE_LONGLONG */
6556 * NT4.x seems to be broken in that it sends large file (64 bit)
6557 * lockingX calls even if the CAP_LARGE_FILES was *not*
6558 * negotiated. For boxes without large unsigned ints truncate the
6559 * lock count by dropping the top 32 bits.
6562 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6563 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6564 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6565 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6566 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6569 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6570 #endif /* HAVE_LONGLONG */
6576 #if !defined(HAVE_LONGLONG)
6577 /****************************************************************************
6578 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6579 ****************************************************************************/
6581 static uint32 map_lock_offset(uint32 high, uint32 low)
6585 uint32 highcopy = high;
6588 * Try and find out how many significant bits there are in high.
6591 for(i = 0; highcopy; i++)
6595 * We use 31 bits not 32 here as POSIX
6596 * lock offsets may not be negative.
6599 mask = (~0) << (31 - i);
6602 return 0; /* Fail. */
6608 #endif /* !defined(HAVE_LONGLONG) */
6610 /****************************************************************************
6611 Get a lock offset, dealing with large offset requests.
6612 ****************************************************************************/
6614 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6615 bool large_file_format, bool *err)
6617 uint64_t offset = 0;
6621 if(!large_file_format) {
6622 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6625 #if defined(HAVE_LONGLONG)
6626 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6627 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6628 #else /* HAVE_LONGLONG */
6631 * NT4.x seems to be broken in that it sends large file (64 bit)
6632 * lockingX calls even if the CAP_LARGE_FILES was *not*
6633 * negotiated. For boxes without large unsigned ints mangle the
6634 * lock offset by mapping the top 32 bits onto the lower 32.
6637 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6638 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6639 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6642 if((new_low = map_lock_offset(high, low)) == 0) {
6644 return (uint64_t)-1;
6647 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6648 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6649 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6650 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6653 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6654 #endif /* HAVE_LONGLONG */
6660 /****************************************************************************
6661 Reply to a lockingX request.
6662 ****************************************************************************/
6664 void reply_lockingX(struct smb_request *req)
6666 connection_struct *conn = req->conn;
6668 unsigned char locktype;
6669 unsigned char oplocklevel;
6672 uint64_t count = 0, offset = 0;
6676 const uint8_t *data;
6677 bool large_file_format;
6679 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6681 START_PROFILE(SMBlockingX);
6684 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6685 END_PROFILE(SMBlockingX);
6689 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
6690 locktype = CVAL(req->vwv+3, 0);
6691 oplocklevel = CVAL(req->vwv+3, 1);
6692 num_ulocks = SVAL(req->vwv+6, 0);
6693 num_locks = SVAL(req->vwv+7, 0);
6694 lock_timeout = IVAL(req->vwv+4, 0);
6695 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6697 if (!check_fsp(conn, req, fsp)) {
6698 END_PROFILE(SMBlockingX);
6704 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6705 /* we don't support these - and CANCEL_LOCK makes w2k
6706 and XP reboot so I don't really want to be
6707 compatible! (tridge) */
6708 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6709 END_PROFILE(SMBlockingX);
6713 /* Check if this is an oplock break on a file
6714 we have granted an oplock on.
6716 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6717 /* Client can insist on breaking to none. */
6718 bool break_to_none = (oplocklevel == 0);
6721 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6722 "for fnum = %d\n", (unsigned int)oplocklevel,
6726 * Make sure we have granted an exclusive or batch oplock on
6730 if (fsp->oplock_type == 0) {
6732 /* The Samba4 nbench simulator doesn't understand
6733 the difference between break to level2 and break
6734 to none from level2 - it sends oplock break
6735 replies in both cases. Don't keep logging an error
6736 message here - just ignore it. JRA. */
6738 DEBUG(5,("reply_lockingX: Error : oplock break from "
6739 "client for fnum = %d (oplock=%d) and no "
6740 "oplock granted on this file (%s).\n",
6741 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
6743 /* if this is a pure oplock break request then don't
6745 if (num_locks == 0 && num_ulocks == 0) {
6746 END_PROFILE(SMBlockingX);
6749 END_PROFILE(SMBlockingX);
6750 reply_doserror(req, ERRDOS, ERRlock);
6755 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6757 result = remove_oplock(fsp);
6759 result = downgrade_oplock(fsp);
6763 DEBUG(0, ("reply_lockingX: error in removing "
6764 "oplock on file %s\n", fsp->fsp_name));
6765 /* Hmmm. Is this panic justified? */
6766 smb_panic("internal tdb error");
6769 reply_to_oplock_break_requests(fsp);
6771 /* if this is a pure oplock break request then don't send a
6773 if (num_locks == 0 && num_ulocks == 0) {
6774 /* Sanity check - ensure a pure oplock break is not a
6776 if(CVAL(req->vwv+0, 0) != 0xff)
6777 DEBUG(0,("reply_lockingX: Error : pure oplock "
6778 "break is a chained %d request !\n",
6779 (unsigned int)CVAL(req->vwv+0, 0)));
6780 END_PROFILE(SMBlockingX);
6786 * We do this check *after* we have checked this is not a oplock break
6787 * response message. JRA.
6790 release_level_2_oplocks_on_change(fsp);
6793 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6794 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6795 END_PROFILE(SMBlockingX);
6799 /* Data now points at the beginning of the list
6800 of smb_unlkrng structs */
6801 for(i = 0; i < (int)num_ulocks; i++) {
6802 lock_pid = get_lock_pid( data, i, large_file_format);
6803 count = get_lock_count( data, i, large_file_format);
6804 offset = get_lock_offset( data, i, large_file_format, &err);
6807 * There is no error code marked "stupid client bug".... :-).
6810 END_PROFILE(SMBlockingX);
6811 reply_doserror(req, ERRDOS, ERRnoaccess);
6815 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6816 "pid %u, file %s\n", (double)offset, (double)count,
6817 (unsigned int)lock_pid, fsp->fsp_name ));
6819 status = do_unlock(smbd_messaging_context(),
6826 if (NT_STATUS_V(status)) {
6827 END_PROFILE(SMBlockingX);
6828 reply_nterror(req, status);
6833 /* Setup the timeout in seconds. */
6835 if (!lp_blocking_locks(SNUM(conn))) {
6839 /* Now do any requested locks */
6840 data += ((large_file_format ? 20 : 10)*num_ulocks);
6842 /* Data now points at the beginning of the list
6843 of smb_lkrng structs */
6845 for(i = 0; i < (int)num_locks; i++) {
6846 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
6847 READ_LOCK:WRITE_LOCK);
6848 lock_pid = get_lock_pid( data, i, large_file_format);
6849 count = get_lock_count( data, i, large_file_format);
6850 offset = get_lock_offset( data, i, large_file_format, &err);
6853 * There is no error code marked "stupid client bug".... :-).
6856 END_PROFILE(SMBlockingX);
6857 reply_doserror(req, ERRDOS, ERRnoaccess);
6861 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6862 "%u, file %s timeout = %d\n", (double)offset,
6863 (double)count, (unsigned int)lock_pid,
6864 fsp->fsp_name, (int)lock_timeout ));
6866 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6867 if (lp_blocking_locks(SNUM(conn))) {
6869 /* Schedule a message to ourselves to
6870 remove the blocking lock record and
6871 return the right error. */
6873 if (!blocking_lock_cancel(fsp,
6879 NT_STATUS_FILE_LOCK_CONFLICT)) {
6880 END_PROFILE(SMBlockingX);
6885 ERRcancelviolation));
6889 /* Remove a matching pending lock. */
6890 status = do_lock_cancel(fsp,
6896 bool blocking_lock = lock_timeout ? True : False;
6897 bool defer_lock = False;
6898 struct byte_range_lock *br_lck;
6899 uint32 block_smbpid;
6901 br_lck = do_lock(smbd_messaging_context(),
6912 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6913 /* Windows internal resolution for blocking locks seems
6914 to be about 200ms... Don't wait for less than that. JRA. */
6915 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
6916 lock_timeout = lp_lock_spin_time();
6921 /* This heuristic seems to match W2K3 very well. If a
6922 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
6923 it pretends we asked for a timeout of between 150 - 300 milliseconds as
6924 far as I can tell. Replacement for do_lock_spin(). JRA. */
6926 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
6927 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
6929 lock_timeout = lp_lock_spin_time();
6932 if (br_lck && defer_lock) {
6934 * A blocking lock was requested. Package up
6935 * this smb into a queued request and push it
6936 * onto the blocking lock queue.
6938 if(push_blocking_lock_request(br_lck,
6949 TALLOC_FREE(br_lck);
6950 END_PROFILE(SMBlockingX);
6955 TALLOC_FREE(br_lck);
6958 if (NT_STATUS_V(status)) {
6959 END_PROFILE(SMBlockingX);
6960 reply_nterror(req, status);
6965 /* If any of the above locks failed, then we must unlock
6966 all of the previous locks (X/Open spec). */
6968 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
6972 * Ensure we don't do a remove on the lock that just failed,
6973 * as under POSIX rules, if we have a lock already there, we
6974 * will delete it (and we shouldn't) .....
6976 for(i--; i >= 0; i--) {
6977 lock_pid = get_lock_pid( data, i, large_file_format);
6978 count = get_lock_count( data, i, large_file_format);
6979 offset = get_lock_offset( data, i, large_file_format,
6983 * There is no error code marked "stupid client
6987 END_PROFILE(SMBlockingX);
6988 reply_doserror(req, ERRDOS, ERRnoaccess);
6992 do_unlock(smbd_messaging_context(),
6999 END_PROFILE(SMBlockingX);
7000 reply_nterror(req, status);
7004 reply_outbuf(req, 2, 0);
7006 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7007 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7009 END_PROFILE(SMBlockingX);
7014 #define DBGC_CLASS DBGC_ALL
7016 /****************************************************************************
7017 Reply to a SMBreadbmpx (read block multiplex) request.
7018 Always reply with an error, if someone has a platform really needs this,
7019 please contact vl@samba.org
7020 ****************************************************************************/
7022 void reply_readbmpx(struct smb_request *req)
7024 START_PROFILE(SMBreadBmpx);
7025 reply_doserror(req, ERRSRV, ERRuseSTD);
7026 END_PROFILE(SMBreadBmpx);
7030 /****************************************************************************
7031 Reply to a SMBreadbs (read block multiplex secondary) request.
7032 Always reply with an error, if someone has a platform really needs this,
7033 please contact vl@samba.org
7034 ****************************************************************************/
7036 void reply_readbs(struct smb_request *req)
7038 START_PROFILE(SMBreadBs);
7039 reply_doserror(req, ERRSRV, ERRuseSTD);
7040 END_PROFILE(SMBreadBs);
7044 /****************************************************************************
7045 Reply to a SMBsetattrE.
7046 ****************************************************************************/
7048 void reply_setattrE(struct smb_request *req)
7050 connection_struct *conn = req->conn;
7051 struct timespec ts[2];
7053 SMB_STRUCT_STAT sbuf;
7056 START_PROFILE(SMBsetattrE);
7059 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7060 END_PROFILE(SMBsetattrE);
7064 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7066 if(!fsp || (fsp->conn != conn)) {
7067 reply_doserror(req, ERRDOS, ERRbadfid);
7068 END_PROFILE(SMBsetattrE);
7074 * Convert the DOS times into unix times. Ignore create
7075 * time as UNIX can't set this.
7078 ts[0] = convert_time_t_to_timespec(
7079 srv_make_unix_date2(req->vwv+3)); /* atime. */
7080 ts[1] = convert_time_t_to_timespec(
7081 srv_make_unix_date2(req->vwv+5)); /* mtime. */
7083 reply_outbuf(req, 0, 0);
7086 * Patch from Ray Frush <frush@engr.colostate.edu>
7087 * Sometimes times are sent as zero - ignore them.
7090 /* Ensure we have a valid stat struct for the source. */
7091 if (fsp->fh->fd != -1) {
7092 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7093 status = map_nt_error_from_unix(errno);
7094 reply_nterror(req, status);
7095 END_PROFILE(SMBsetattrE);
7099 if (SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf) == -1) {
7100 status = map_nt_error_from_unix(errno);
7101 reply_nterror(req, status);
7102 END_PROFILE(SMBsetattrE);
7107 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7109 if (!NT_STATUS_IS_OK(status)) {
7110 reply_doserror(req, ERRDOS, ERRnoaccess);
7111 END_PROFILE(SMBsetattrE);
7115 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
7117 (unsigned int)ts[0].tv_sec,
7118 (unsigned int)ts[1].tv_sec));
7120 END_PROFILE(SMBsetattrE);
7125 /* Back from the dead for OS/2..... JRA. */
7127 /****************************************************************************
7128 Reply to a SMBwritebmpx (write block multiplex primary) request.
7129 Always reply with an error, if someone has a platform really needs this,
7130 please contact vl@samba.org
7131 ****************************************************************************/
7133 void reply_writebmpx(struct smb_request *req)
7135 START_PROFILE(SMBwriteBmpx);
7136 reply_doserror(req, ERRSRV, ERRuseSTD);
7137 END_PROFILE(SMBwriteBmpx);
7141 /****************************************************************************
7142 Reply to a SMBwritebs (write block multiplex secondary) request.
7143 Always reply with an error, if someone has a platform really needs this,
7144 please contact vl@samba.org
7145 ****************************************************************************/
7147 void reply_writebs(struct smb_request *req)
7149 START_PROFILE(SMBwriteBs);
7150 reply_doserror(req, ERRSRV, ERRuseSTD);
7151 END_PROFILE(SMBwriteBs);
7155 /****************************************************************************
7156 Reply to a SMBgetattrE.
7157 ****************************************************************************/
7159 void reply_getattrE(struct smb_request *req)
7161 connection_struct *conn = req->conn;
7162 SMB_STRUCT_STAT sbuf;
7165 struct timespec create_ts;
7167 START_PROFILE(SMBgetattrE);
7170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7171 END_PROFILE(SMBgetattrE);
7175 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7177 if(!fsp || (fsp->conn != conn)) {
7178 reply_doserror(req, ERRDOS, ERRbadfid);
7179 END_PROFILE(SMBgetattrE);
7183 /* Do an fstat on this file */
7184 if(fsp_stat(fsp, &sbuf)) {
7185 reply_unixerror(req, ERRDOS, ERRnoaccess);
7186 END_PROFILE(SMBgetattrE);
7190 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7193 * Convert the times into dos times. Set create
7194 * date to be last modify date as UNIX doesn't save
7198 reply_outbuf(req, 11, 0);
7200 create_ts = get_create_timespec(&sbuf,
7201 lp_fake_dir_create_times(SNUM(conn)));
7202 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7203 srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7204 /* Should we check pending modtime here ? JRA */
7205 srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7208 SIVAL(req->outbuf, smb_vwv6, 0);
7209 SIVAL(req->outbuf, smb_vwv8, 0);
7211 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
7212 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7213 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7215 SSVAL(req->outbuf,smb_vwv10, mode);
7217 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7219 END_PROFILE(SMBgetattrE);