2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "smbd/globals.h"
30 extern enum protocol_types Protocol;
32 /****************************************************************************
33 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
34 path or anything including wildcards.
35 We're assuming here that '/' is not the second byte in any multibyte char
36 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
38 ****************************************************************************/
40 /* Custom version for processing POSIX paths. */
41 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
43 static NTSTATUS check_path_syntax_internal(char *path,
45 bool *p_last_component_contains_wcard)
49 NTSTATUS ret = NT_STATUS_OK;
50 bool start_of_name_component = True;
51 bool stream_started = false;
53 *p_last_component_contains_wcard = False;
60 return NT_STATUS_OBJECT_NAME_INVALID;
63 return NT_STATUS_OBJECT_NAME_INVALID;
65 if (strchr_m(&s[1], ':')) {
66 return NT_STATUS_OBJECT_NAME_INVALID;
68 if (StrCaseCmp(s, ":$DATA") != 0) {
69 return NT_STATUS_INVALID_PARAMETER;
75 if (!posix_path && !stream_started && *s == ':') {
76 if (*p_last_component_contains_wcard) {
77 return NT_STATUS_OBJECT_NAME_INVALID;
79 /* Stream names allow more characters than file names.
80 We're overloading posix_path here to allow a wider
81 range of characters. If stream_started is true this
82 is still a Windows path even if posix_path is true.
85 stream_started = true;
86 start_of_name_component = false;
90 return NT_STATUS_OBJECT_NAME_INVALID;
94 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
96 * Safe to assume is not the second part of a mb char
97 * as this is handled below.
99 /* Eat multiple '/' or '\\' */
100 while (IS_PATH_SEP(*s,posix_path)) {
103 if ((d != path) && (*s != '\0')) {
104 /* We only care about non-leading or trailing '/' or '\\' */
108 start_of_name_component = True;
110 *p_last_component_contains_wcard = False;
114 if (start_of_name_component) {
115 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
116 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
119 * No mb char starts with '.' so we're safe checking the directory separator here.
122 /* If we just added a '/' - delete it */
123 if ((d > path) && (*(d-1) == '/')) {
128 /* Are we at the start ? Can't go back further if so. */
130 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
133 /* Go back one level... */
134 /* We know this is safe as '/' cannot be part of a mb sequence. */
135 /* NOTE - if this assumption is invalid we are not in good shape... */
136 /* Decrement d first as d points to the *next* char to write into. */
137 for (d--; d > path; d--) {
141 s += 2; /* Else go past the .. */
142 /* We're still at the start of a name component, just the previous one. */
145 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
157 if (*s <= 0x1f || *s == '|') {
158 return NT_STATUS_OBJECT_NAME_INVALID;
166 *p_last_component_contains_wcard = True;
175 /* Get the size of the next MB character. */
176 next_codepoint(s,&siz);
194 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
196 return NT_STATUS_INVALID_PARAMETER;
199 start_of_name_component = False;
207 /****************************************************************************
208 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
209 No wildcards allowed.
210 ****************************************************************************/
212 NTSTATUS check_path_syntax(char *path)
215 return check_path_syntax_internal(path, False, &ignore);
218 /****************************************************************************
219 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
220 Wildcards allowed - p_contains_wcard returns true if the last component contained
222 ****************************************************************************/
224 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
226 return check_path_syntax_internal(path, False, p_contains_wcard);
229 /****************************************************************************
230 Check the path for a POSIX client.
231 We're assuming here that '/' is not the second byte in any multibyte char
232 set (a safe assumption).
233 ****************************************************************************/
235 NTSTATUS check_path_syntax_posix(char *path)
238 return check_path_syntax_internal(path, True, &ignore);
241 /****************************************************************************
242 Pull a string and check the path allowing a wilcard - provide for error return.
243 ****************************************************************************/
245 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
246 const char *base_ptr,
253 bool *contains_wcard)
259 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
263 *err = NT_STATUS_INVALID_PARAMETER;
267 *contains_wcard = False;
269 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
271 * For a DFS path the function parse_dfs_path()
272 * will do the path processing, just make a copy.
278 if (lp_posix_pathnames()) {
279 *err = check_path_syntax_posix(*pp_dest);
281 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
287 /****************************************************************************
288 Pull a string and check the path - provide for error return.
289 ****************************************************************************/
291 size_t srvstr_get_path(TALLOC_CTX *ctx,
292 const char *base_ptr,
301 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
302 src_len, flags, err, &ignore);
305 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
306 char **pp_dest, const char *src, int flags,
307 NTSTATUS *err, bool *contains_wcard)
309 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
310 pp_dest, src, smbreq_bufrem(req, src),
311 flags, err, contains_wcard);
314 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
315 char **pp_dest, const char *src, int flags,
319 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
320 flags, err, &ignore);
323 /****************************************************************************
324 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
325 ****************************************************************************/
327 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
330 if (!(fsp) || !(conn)) {
331 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
334 if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
335 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
341 /****************************************************************************
342 Check if we have a correct fsp pointing to a file.
343 ****************************************************************************/
345 bool check_fsp(connection_struct *conn, struct smb_request *req,
348 if (!check_fsp_open(conn, req, fsp)) {
351 if ((fsp)->is_directory) {
352 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
355 if ((fsp)->fh->fd == -1) {
356 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
359 (fsp)->num_smb_operations++;
363 /****************************************************************************
364 Check if we have a correct fsp pointing to a quota fake file. Replacement for
365 the CHECK_NTQUOTA_HANDLE_OK macro.
366 ****************************************************************************/
368 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
371 if (!check_fsp_open(conn, req, fsp)) {
375 if (fsp->is_directory) {
379 if (fsp->fake_file_handle == NULL) {
383 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
387 if (fsp->fake_file_handle->private_data == NULL) {
394 /****************************************************************************
395 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
396 ****************************************************************************/
398 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
401 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
402 && (req->vuid == (fsp)->vuid)) {
406 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
410 /****************************************************************************
411 Reply to a (netbios-level) special message.
412 ****************************************************************************/
414 void reply_special(char *inbuf)
416 int msg_type = CVAL(inbuf,0);
417 int msg_flags = CVAL(inbuf,1);
422 * We only really use 4 bytes of the outbuf, but for the smb_setlen
423 * calculation & friends (srv_send_smb uses that) we need the full smb
426 char outbuf[smb_size];
430 memset(outbuf, '\0', sizeof(outbuf));
432 smb_setlen(outbuf,0);
435 case 0x81: /* session request */
437 if (already_got_session) {
438 exit_server_cleanly("multiple session request not permitted");
441 SCVAL(outbuf,0,0x82);
443 if (name_len(inbuf+4) > 50 ||
444 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
445 DEBUG(0,("Invalid name length in session request\n"));
448 name_extract(inbuf,4,name1);
449 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
450 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
453 set_local_machine_name(name1, True);
454 set_remote_machine_name(name2, True);
456 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
457 get_local_machine_name(), get_remote_machine_name(),
460 if (name_type == 'R') {
461 /* We are being asked for a pathworks session ---
463 SCVAL(outbuf, 0,0x83);
467 /* only add the client's machine name to the list
468 of possibly valid usernames if we are operating
469 in share mode security */
470 if (lp_security() == SEC_SHARE) {
471 add_session_user(get_remote_machine_name());
474 reload_services(True);
477 already_got_session = True;
480 case 0x89: /* session keepalive request
481 (some old clients produce this?) */
482 SCVAL(outbuf,0,SMBkeepalive);
486 case 0x82: /* positive session response */
487 case 0x83: /* negative session response */
488 case 0x84: /* retarget session response */
489 DEBUG(0,("Unexpected session response\n"));
492 case SMBkeepalive: /* session keepalive */
497 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
498 msg_type, msg_flags));
500 srv_send_smb(smbd_server_fd(), outbuf, false, NULL);
504 /****************************************************************************
506 conn POINTER CAN BE NULL HERE !
507 ****************************************************************************/
509 void reply_tcon(struct smb_request *req)
511 connection_struct *conn = req->conn;
513 char *service_buf = NULL;
514 char *password = NULL;
519 DATA_BLOB password_blob;
520 TALLOC_CTX *ctx = talloc_tos();
522 START_PROFILE(SMBtcon);
524 if (req->buflen < 4) {
525 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
526 END_PROFILE(SMBtcon);
530 p = (const char *)req->buf + 1;
531 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
533 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
535 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
538 if (service_buf == NULL || password == NULL || dev == NULL) {
539 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
540 END_PROFILE(SMBtcon);
543 p = strrchr_m(service_buf,'\\');
547 service = service_buf;
550 password_blob = data_blob(password, pwlen+1);
552 conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
555 data_blob_clear_free(&password_blob);
558 reply_nterror(req, nt_status);
559 END_PROFILE(SMBtcon);
563 reply_outbuf(req, 2, 0);
564 SSVAL(req->outbuf,smb_vwv0,max_recv);
565 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
566 SSVAL(req->outbuf,smb_tid,conn->cnum);
568 DEBUG(3,("tcon service=%s cnum=%d\n",
569 service, conn->cnum));
571 END_PROFILE(SMBtcon);
575 /****************************************************************************
576 Reply to a tcon and X.
577 conn POINTER CAN BE NULL HERE !
578 ****************************************************************************/
580 void reply_tcon_and_X(struct smb_request *req)
582 connection_struct *conn = req->conn;
583 const char *service = NULL;
585 TALLOC_CTX *ctx = talloc_tos();
586 /* what the cleint thinks the device is */
587 char *client_devicetype = NULL;
588 /* what the server tells the client the share represents */
589 const char *server_devicetype;
596 START_PROFILE(SMBtconX);
599 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
600 END_PROFILE(SMBtconX);
604 passlen = SVAL(req->vwv+3, 0);
605 tcon_flags = SVAL(req->vwv+2, 0);
607 /* we might have to close an old one */
608 if ((tcon_flags & 0x1) && conn) {
609 close_cnum(conn,req->vuid);
614 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
615 reply_doserror(req, ERRDOS, ERRbuftoosmall);
616 END_PROFILE(SMBtconX);
620 if (global_encrypted_passwords_negotiated) {
621 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
622 if (lp_security() == SEC_SHARE) {
624 * Security = share always has a pad byte
625 * after the password.
627 p = (const char *)req->buf + passlen + 1;
629 p = (const char *)req->buf + passlen;
632 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
633 /* Ensure correct termination */
634 password.data[passlen]=0;
635 p = (const char *)req->buf + passlen + 1;
638 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
641 data_blob_clear_free(&password);
642 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
643 END_PROFILE(SMBtconX);
648 * the service name can be either: \\server\share
649 * or share directly like on the DELL PowerVault 705
652 q = strchr_m(path+2,'\\');
654 data_blob_clear_free(&password);
655 reply_doserror(req, ERRDOS, ERRnosuchshare);
656 END_PROFILE(SMBtconX);
664 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
665 &client_devicetype, p,
666 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
668 if (client_devicetype == NULL) {
669 data_blob_clear_free(&password);
670 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
671 END_PROFILE(SMBtconX);
675 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
677 conn = make_connection(service, password, client_devicetype,
678 req->vuid, &nt_status);
681 data_blob_clear_free(&password);
684 reply_nterror(req, nt_status);
685 END_PROFILE(SMBtconX);
690 server_devicetype = "IPC";
691 else if ( IS_PRINT(conn) )
692 server_devicetype = "LPT1:";
694 server_devicetype = "A:";
696 if (Protocol < PROTOCOL_NT1) {
697 reply_outbuf(req, 2, 0);
698 if (message_push_string(&req->outbuf, server_devicetype,
699 STR_TERMINATE|STR_ASCII) == -1) {
700 reply_nterror(req, NT_STATUS_NO_MEMORY);
701 END_PROFILE(SMBtconX);
705 /* NT sets the fstype of IPC$ to the null string */
706 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
708 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
709 /* Return permissions. */
713 reply_outbuf(req, 7, 0);
716 perm1 = FILE_ALL_ACCESS;
717 perm2 = FILE_ALL_ACCESS;
719 perm1 = CAN_WRITE(conn) ?
724 SIVAL(req->outbuf, smb_vwv3, perm1);
725 SIVAL(req->outbuf, smb_vwv5, perm2);
727 reply_outbuf(req, 3, 0);
730 if ((message_push_string(&req->outbuf, server_devicetype,
731 STR_TERMINATE|STR_ASCII) == -1)
732 || (message_push_string(&req->outbuf, fstype,
733 STR_TERMINATE) == -1)) {
734 reply_nterror(req, NT_STATUS_NO_MEMORY);
735 END_PROFILE(SMBtconX);
739 /* what does setting this bit do? It is set by NT4 and
740 may affect the ability to autorun mounted cdroms */
741 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
742 (lp_csc_policy(SNUM(conn)) << 2));
744 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
745 DEBUG(2,("Serving %s as a Dfs root\n",
746 lp_servicename(SNUM(conn)) ));
747 SSVAL(req->outbuf, smb_vwv2,
748 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
753 DEBUG(3,("tconX service=%s \n",
756 /* set the incoming and outgoing tid to the just created one */
757 SSVAL(req->inbuf,smb_tid,conn->cnum);
758 SSVAL(req->outbuf,smb_tid,conn->cnum);
760 END_PROFILE(SMBtconX);
766 /****************************************************************************
767 Reply to an unknown type.
768 ****************************************************************************/
770 void reply_unknown_new(struct smb_request *req, uint8 type)
772 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
773 smb_fn_name(type), type, type));
774 reply_doserror(req, ERRSRV, ERRunknownsmb);
778 /****************************************************************************
780 conn POINTER CAN BE NULL HERE !
781 ****************************************************************************/
783 void reply_ioctl(struct smb_request *req)
785 connection_struct *conn = req->conn;
792 START_PROFILE(SMBioctl);
795 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
796 END_PROFILE(SMBioctl);
800 device = SVAL(req->vwv+1, 0);
801 function = SVAL(req->vwv+2, 0);
802 ioctl_code = (device << 16) + function;
804 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
806 switch (ioctl_code) {
807 case IOCTL_QUERY_JOB_INFO:
811 reply_doserror(req, ERRSRV, ERRnosupport);
812 END_PROFILE(SMBioctl);
816 reply_outbuf(req, 8, replysize+1);
817 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
818 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
819 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
820 p = smb_buf(req->outbuf);
821 memset(p, '\0', replysize+1); /* valgrind-safe. */
822 p += 1; /* Allow for alignment */
824 switch (ioctl_code) {
825 case IOCTL_QUERY_JOB_INFO:
827 files_struct *fsp = file_fsp(
828 req, SVAL(req->vwv+0, 0));
830 reply_doserror(req, ERRDOS, ERRbadfid);
831 END_PROFILE(SMBioctl);
834 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
835 srvstr_push((char *)req->outbuf, req->flags2, p+2,
837 STR_TERMINATE|STR_ASCII);
839 srvstr_push((char *)req->outbuf, req->flags2,
840 p+18, lp_servicename(SNUM(conn)),
841 13, STR_TERMINATE|STR_ASCII);
849 END_PROFILE(SMBioctl);
853 /****************************************************************************
854 Strange checkpath NTSTATUS mapping.
855 ****************************************************************************/
857 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
859 /* Strange DOS error code semantics only for checkpath... */
860 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
861 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
862 /* We need to map to ERRbadpath */
863 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
869 /****************************************************************************
870 Reply to a checkpath.
871 ****************************************************************************/
873 void reply_checkpath(struct smb_request *req)
875 connection_struct *conn = req->conn;
877 SMB_STRUCT_STAT sbuf;
879 TALLOC_CTX *ctx = talloc_tos();
881 START_PROFILE(SMBcheckpath);
883 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
884 STR_TERMINATE, &status);
886 if (!NT_STATUS_IS_OK(status)) {
887 status = map_checkpath_error(req->flags2, status);
888 reply_nterror(req, status);
889 END_PROFILE(SMBcheckpath);
893 status = resolve_dfspath(ctx, conn,
894 req->flags2 & FLAGS2_DFS_PATHNAMES,
897 if (!NT_STATUS_IS_OK(status)) {
898 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
899 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
901 END_PROFILE(SMBcheckpath);
907 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
909 status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf);
910 if (!NT_STATUS_IS_OK(status)) {
914 status = check_name(conn, name);
915 if (!NT_STATUS_IS_OK(status)) {
916 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
920 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
921 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
922 status = map_nt_error_from_unix(errno);
926 if (!S_ISDIR(sbuf.st_mode)) {
927 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
929 END_PROFILE(SMBcheckpath);
933 reply_outbuf(req, 0, 0);
935 END_PROFILE(SMBcheckpath);
940 END_PROFILE(SMBcheckpath);
942 /* We special case this - as when a Windows machine
943 is parsing a path is steps through the components
944 one at a time - if a component fails it expects
945 ERRbadpath, not ERRbadfile.
947 status = map_checkpath_error(req->flags2, status);
948 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
950 * Windows returns different error codes if
951 * the parent directory is valid but not the
952 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
953 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
954 * if the path is invalid.
956 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
961 reply_nterror(req, status);
964 /****************************************************************************
966 ****************************************************************************/
968 void reply_getatr(struct smb_request *req)
970 connection_struct *conn = req->conn;
972 SMB_STRUCT_STAT sbuf;
978 TALLOC_CTX *ctx = talloc_tos();
980 START_PROFILE(SMBgetatr);
982 p = (const char *)req->buf + 1;
983 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
984 if (!NT_STATUS_IS_OK(status)) {
985 reply_nterror(req, status);
986 END_PROFILE(SMBgetatr);
990 status = resolve_dfspath(ctx, conn,
991 req->flags2 & FLAGS2_DFS_PATHNAMES,
994 if (!NT_STATUS_IS_OK(status)) {
995 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
996 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
998 END_PROFILE(SMBgetatr);
1001 reply_nterror(req, status);
1002 END_PROFILE(SMBgetatr);
1006 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1007 under WfWg - weird! */
1008 if (*fname == '\0') {
1009 mode = aHIDDEN | aDIR;
1010 if (!CAN_WRITE(conn)) {
1016 status = unix_convert(ctx, conn, fname, False, &fname, NULL,&sbuf);
1017 if (!NT_STATUS_IS_OK(status)) {
1018 reply_nterror(req, status);
1019 END_PROFILE(SMBgetatr);
1022 status = check_name(conn, fname);
1023 if (!NT_STATUS_IS_OK(status)) {
1024 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1025 reply_nterror(req, status);
1026 END_PROFILE(SMBgetatr);
1029 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
1030 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1031 reply_unixerror(req, ERRDOS,ERRbadfile);
1032 END_PROFILE(SMBgetatr);
1036 mode = dos_mode(conn,fname,&sbuf);
1037 size = sbuf.st_size;
1038 mtime = sbuf.st_mtime;
1044 reply_outbuf(req, 10, 0);
1046 SSVAL(req->outbuf,smb_vwv0,mode);
1047 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1048 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1050 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1052 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1054 if (Protocol >= PROTOCOL_NT1) {
1055 SSVAL(req->outbuf, smb_flg2,
1056 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1059 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1061 END_PROFILE(SMBgetatr);
1065 /****************************************************************************
1067 ****************************************************************************/
1069 void reply_setatr(struct smb_request *req)
1071 struct smb_file_time ft;
1072 connection_struct *conn = req->conn;
1076 SMB_STRUCT_STAT sbuf;
1079 TALLOC_CTX *ctx = talloc_tos();
1081 START_PROFILE(SMBsetatr);
1086 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1090 p = (const char *)req->buf + 1;
1091 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1092 if (!NT_STATUS_IS_OK(status)) {
1093 reply_nterror(req, status);
1094 END_PROFILE(SMBsetatr);
1098 status = resolve_dfspath(ctx, conn,
1099 req->flags2 & FLAGS2_DFS_PATHNAMES,
1102 if (!NT_STATUS_IS_OK(status)) {
1103 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1104 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1105 ERRSRV, ERRbadpath);
1106 END_PROFILE(SMBsetatr);
1109 reply_nterror(req, status);
1110 END_PROFILE(SMBsetatr);
1114 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
1115 if (!NT_STATUS_IS_OK(status)) {
1116 reply_nterror(req, status);
1117 END_PROFILE(SMBsetatr);
1121 status = check_name(conn, fname);
1122 if (!NT_STATUS_IS_OK(status)) {
1123 reply_nterror(req, status);
1124 END_PROFILE(SMBsetatr);
1128 if (fname[0] == '.' && fname[1] == '\0') {
1130 * Not sure here is the right place to catch this
1131 * condition. Might be moved to somewhere else later -- vl
1133 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1134 END_PROFILE(SMBsetatr);
1138 mode = SVAL(req->vwv+0, 0);
1139 mtime = srv_make_unix_date3(req->vwv+1);
1141 ft.mtime = convert_time_t_to_timespec(mtime);
1142 status = smb_set_file_time(conn, NULL, fname,
1144 if (!NT_STATUS_IS_OK(status)) {
1145 reply_unixerror(req, ERRDOS, ERRnoaccess);
1146 END_PROFILE(SMBsetatr);
1150 if (mode != FILE_ATTRIBUTE_NORMAL) {
1151 if (VALID_STAT_OF_DIR(sbuf))
1156 if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) {
1157 reply_unixerror(req, ERRDOS, ERRnoaccess);
1158 END_PROFILE(SMBsetatr);
1163 reply_outbuf(req, 0, 0);
1165 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1167 END_PROFILE(SMBsetatr);
1171 /****************************************************************************
1173 ****************************************************************************/
1175 void reply_dskattr(struct smb_request *req)
1177 connection_struct *conn = req->conn;
1178 uint64_t dfree,dsize,bsize;
1179 START_PROFILE(SMBdskattr);
1181 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1182 reply_unixerror(req, ERRHRD, ERRgeneral);
1183 END_PROFILE(SMBdskattr);
1187 reply_outbuf(req, 5, 0);
1189 if (Protocol <= PROTOCOL_LANMAN2) {
1190 double total_space, free_space;
1191 /* we need to scale this to a number that DOS6 can handle. We
1192 use floating point so we can handle large drives on systems
1193 that don't have 64 bit integers
1195 we end up displaying a maximum of 2G to DOS systems
1197 total_space = dsize * (double)bsize;
1198 free_space = dfree * (double)bsize;
1200 dsize = (uint64_t)((total_space+63*512) / (64*512));
1201 dfree = (uint64_t)((free_space+63*512) / (64*512));
1203 if (dsize > 0xFFFF) dsize = 0xFFFF;
1204 if (dfree > 0xFFFF) dfree = 0xFFFF;
1206 SSVAL(req->outbuf,smb_vwv0,dsize);
1207 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1208 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1209 SSVAL(req->outbuf,smb_vwv3,dfree);
1211 SSVAL(req->outbuf,smb_vwv0,dsize);
1212 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1213 SSVAL(req->outbuf,smb_vwv2,512);
1214 SSVAL(req->outbuf,smb_vwv3,dfree);
1217 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1219 END_PROFILE(SMBdskattr);
1223 /****************************************************************************
1225 Can be called from SMBsearch, SMBffirst or SMBfunique.
1226 ****************************************************************************/
1228 void reply_search(struct smb_request *req)
1230 connection_struct *conn = req->conn;
1231 const char *mask = NULL;
1232 char *directory = NULL;
1238 unsigned int numentries = 0;
1239 unsigned int maxentries = 0;
1240 bool finished = False;
1246 bool check_descend = False;
1247 bool expect_close = False;
1249 bool mask_contains_wcard = False;
1250 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1251 TALLOC_CTX *ctx = talloc_tos();
1252 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1254 START_PROFILE(SMBsearch);
1257 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1258 END_PROFILE(SMBsearch);
1262 if (lp_posix_pathnames()) {
1263 reply_unknown_new(req, req->cmd);
1264 END_PROFILE(SMBsearch);
1268 /* If we were called as SMBffirst then we must expect close. */
1269 if(req->cmd == SMBffirst) {
1270 expect_close = True;
1273 reply_outbuf(req, 1, 3);
1274 maxentries = SVAL(req->vwv+0, 0);
1275 dirtype = SVAL(req->vwv+1, 0);
1276 p = (const char *)req->buf + 1;
1277 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1278 &nt_status, &mask_contains_wcard);
1279 if (!NT_STATUS_IS_OK(nt_status)) {
1280 reply_nterror(req, nt_status);
1281 END_PROFILE(SMBsearch);
1285 nt_status = resolve_dfspath_wcard(ctx, conn,
1286 req->flags2 & FLAGS2_DFS_PATHNAMES,
1289 &mask_contains_wcard);
1290 if (!NT_STATUS_IS_OK(nt_status)) {
1291 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1292 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1293 ERRSRV, ERRbadpath);
1294 END_PROFILE(SMBsearch);
1297 reply_nterror(req, nt_status);
1298 END_PROFILE(SMBsearch);
1303 status_len = SVAL(p, 0);
1306 /* dirtype &= ~aDIR; */
1308 if (status_len == 0) {
1309 SMB_STRUCT_STAT sbuf;
1311 nt_status = unix_convert(ctx, conn, path, True,
1312 &directory, NULL, &sbuf);
1313 if (!NT_STATUS_IS_OK(nt_status)) {
1314 reply_nterror(req, nt_status);
1315 END_PROFILE(SMBsearch);
1319 nt_status = check_name(conn, directory);
1320 if (!NT_STATUS_IS_OK(nt_status)) {
1321 reply_nterror(req, nt_status);
1322 END_PROFILE(SMBsearch);
1326 p = strrchr_m(directory,'/');
1327 if ((p != NULL) && (*directory != '/')) {
1329 directory = talloc_strndup(ctx, directory,
1330 PTR_DIFF(p, directory));
1333 directory = talloc_strdup(ctx,".");
1337 reply_nterror(req, NT_STATUS_NO_MEMORY);
1338 END_PROFILE(SMBsearch);
1342 memset((char *)status,'\0',21);
1343 SCVAL(status,0,(dirtype & 0x1F));
1345 nt_status = dptr_create(conn,
1351 mask_contains_wcard,
1354 if (!NT_STATUS_IS_OK(nt_status)) {
1355 reply_nterror(req, nt_status);
1356 END_PROFILE(SMBsearch);
1359 dptr_num = dptr_dnum(conn->dirptr);
1363 memcpy(status,p,21);
1364 status_dirtype = CVAL(status,0) & 0x1F;
1365 if (status_dirtype != (dirtype & 0x1F)) {
1366 dirtype = status_dirtype;
1369 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1370 if (!conn->dirptr) {
1373 string_set(&conn->dirpath,dptr_path(dptr_num));
1374 mask = dptr_wcard(dptr_num);
1379 * For a 'continue' search we have no string. So
1380 * check from the initial saved string.
1382 mask_contains_wcard = ms_has_wild(mask);
1383 dirtype = dptr_attr(dptr_num);
1386 DEBUG(4,("dptr_num is %d\n",dptr_num));
1388 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1389 dptr_init_search_op(conn->dirptr);
1391 if ((dirtype&0x1F) == aVOLID) {
1392 char buf[DIR_STRUCT_SIZE];
1393 memcpy(buf,status,21);
1394 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1395 0,aVOLID,0,!allow_long_path_components)) {
1396 reply_nterror(req, NT_STATUS_NO_MEMORY);
1397 END_PROFILE(SMBsearch);
1400 dptr_fill(buf+12,dptr_num);
1401 if (dptr_zero(buf+12) && (status_len==0)) {
1406 if (message_push_blob(&req->outbuf,
1407 data_blob_const(buf, sizeof(buf)))
1409 reply_nterror(req, NT_STATUS_NO_MEMORY);
1410 END_PROFILE(SMBsearch);
1418 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1421 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1422 conn->dirpath,lp_dontdescend(SNUM(conn))));
1423 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1424 check_descend = True;
1427 for (i=numentries;(i<maxentries) && !finished;i++) {
1428 finished = !get_dir_entry(ctx,
1439 char buf[DIR_STRUCT_SIZE];
1440 memcpy(buf,status,21);
1441 if (!make_dir_struct(ctx,
1448 !allow_long_path_components)) {
1449 reply_nterror(req, NT_STATUS_NO_MEMORY);
1450 END_PROFILE(SMBsearch);
1453 if (!dptr_fill(buf+12,dptr_num)) {
1456 if (message_push_blob(&req->outbuf,
1457 data_blob_const(buf, sizeof(buf)))
1459 reply_nterror(req, NT_STATUS_NO_MEMORY);
1460 END_PROFILE(SMBsearch);
1470 /* If we were called as SMBffirst with smb_search_id == NULL
1471 and no entries were found then return error and close dirptr
1474 if (numentries == 0) {
1475 dptr_close(&dptr_num);
1476 } else if(expect_close && status_len == 0) {
1477 /* Close the dptr - we know it's gone */
1478 dptr_close(&dptr_num);
1481 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1482 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1483 dptr_close(&dptr_num);
1486 if ((numentries == 0) && !mask_contains_wcard) {
1487 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1488 END_PROFILE(SMBsearch);
1492 SSVAL(req->outbuf,smb_vwv0,numentries);
1493 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1494 SCVAL(smb_buf(req->outbuf),0,5);
1495 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1497 /* The replies here are never long name. */
1498 SSVAL(req->outbuf, smb_flg2,
1499 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1500 if (!allow_long_path_components) {
1501 SSVAL(req->outbuf, smb_flg2,
1502 SVAL(req->outbuf, smb_flg2)
1503 & (~FLAGS2_LONG_PATH_COMPONENTS));
1506 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1507 SSVAL(req->outbuf, smb_flg2,
1508 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1511 directory = dptr_path(dptr_num);
1514 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1515 smb_fn_name(req->cmd),
1517 directory ? directory : "./",
1522 END_PROFILE(SMBsearch);
1526 /****************************************************************************
1527 Reply to a fclose (stop directory search).
1528 ****************************************************************************/
1530 void reply_fclose(struct smb_request *req)
1538 bool path_contains_wcard = False;
1539 TALLOC_CTX *ctx = talloc_tos();
1541 START_PROFILE(SMBfclose);
1543 if (lp_posix_pathnames()) {
1544 reply_unknown_new(req, req->cmd);
1545 END_PROFILE(SMBfclose);
1549 p = (const char *)req->buf + 1;
1550 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1551 &err, &path_contains_wcard);
1552 if (!NT_STATUS_IS_OK(err)) {
1553 reply_nterror(req, err);
1554 END_PROFILE(SMBfclose);
1558 status_len = SVAL(p,0);
1561 if (status_len == 0) {
1562 reply_doserror(req, ERRSRV, ERRsrverror);
1563 END_PROFILE(SMBfclose);
1567 memcpy(status,p,21);
1569 if(dptr_fetch(status+12,&dptr_num)) {
1570 /* Close the dptr - we know it's gone */
1571 dptr_close(&dptr_num);
1574 reply_outbuf(req, 1, 0);
1575 SSVAL(req->outbuf,smb_vwv0,0);
1577 DEBUG(3,("search close\n"));
1579 END_PROFILE(SMBfclose);
1583 /****************************************************************************
1585 ****************************************************************************/
1587 void reply_open(struct smb_request *req)
1589 connection_struct *conn = req->conn;
1595 SMB_STRUCT_STAT sbuf;
1602 uint32 create_disposition;
1603 uint32 create_options = 0;
1605 TALLOC_CTX *ctx = talloc_tos();
1607 START_PROFILE(SMBopen);
1610 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1611 END_PROFILE(SMBopen);
1615 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1616 deny_mode = SVAL(req->vwv+0, 0);
1617 dos_attr = SVAL(req->vwv+1, 0);
1619 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1620 STR_TERMINATE, &status);
1621 if (!NT_STATUS_IS_OK(status)) {
1622 reply_nterror(req, status);
1623 END_PROFILE(SMBopen);
1627 if (!map_open_params_to_ntcreate(
1628 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1629 &share_mode, &create_disposition, &create_options)) {
1630 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1631 END_PROFILE(SMBopen);
1635 status = SMB_VFS_CREATE_FILE(
1638 0, /* root_dir_fid */
1640 CFF_DOS_PATH, /* create_file_flags */
1641 access_mask, /* access_mask */
1642 share_mode, /* share_access */
1643 create_disposition, /* create_disposition*/
1644 create_options, /* create_options */
1645 dos_attr, /* file_attributes */
1646 oplock_request, /* oplock_request */
1647 0, /* allocation_size */
1654 if (!NT_STATUS_IS_OK(status)) {
1655 if (open_was_deferred(req->mid)) {
1656 /* We have re-scheduled this call. */
1657 END_PROFILE(SMBopen);
1660 reply_openerror(req, status);
1661 END_PROFILE(SMBopen);
1665 size = sbuf.st_size;
1666 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1667 mtime = sbuf.st_mtime;
1670 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1671 close_file(req, fsp, ERROR_CLOSE);
1672 reply_doserror(req, ERRDOS,ERRnoaccess);
1673 END_PROFILE(SMBopen);
1677 reply_outbuf(req, 7, 0);
1678 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1679 SSVAL(req->outbuf,smb_vwv1,fattr);
1680 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1681 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1683 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1685 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1686 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1688 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1689 SCVAL(req->outbuf,smb_flg,
1690 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1693 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1694 SCVAL(req->outbuf,smb_flg,
1695 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1697 END_PROFILE(SMBopen);
1701 /****************************************************************************
1702 Reply to an open and X.
1703 ****************************************************************************/
1705 void reply_open_and_X(struct smb_request *req)
1707 connection_struct *conn = req->conn;
1712 /* Breakout the oplock request bits so we can set the
1713 reply bits separately. */
1714 int ex_oplock_request;
1715 int core_oplock_request;
1718 int smb_sattr = SVAL(req->vwv+4, 0);
1719 uint32 smb_time = make_unix_date3(req->vwv+6);
1724 SMB_STRUCT_STAT sbuf;
1728 uint64_t allocation_size;
1729 ssize_t retval = -1;
1732 uint32 create_disposition;
1733 uint32 create_options = 0;
1734 TALLOC_CTX *ctx = talloc_tos();
1736 START_PROFILE(SMBopenX);
1738 if (req->wct < 15) {
1739 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1740 END_PROFILE(SMBopenX);
1744 open_flags = SVAL(req->vwv+2, 0);
1745 deny_mode = SVAL(req->vwv+3, 0);
1746 smb_attr = SVAL(req->vwv+5, 0);
1747 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1748 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1749 oplock_request = ex_oplock_request | core_oplock_request;
1750 smb_ofun = SVAL(req->vwv+8, 0);
1751 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1753 /* If it's an IPC, pass off the pipe handler. */
1755 if (lp_nt_pipe_support()) {
1756 reply_open_pipe_and_X(conn, req);
1758 reply_doserror(req, ERRSRV, ERRaccess);
1760 END_PROFILE(SMBopenX);
1764 /* XXXX we need to handle passed times, sattr and flags */
1765 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1766 STR_TERMINATE, &status);
1767 if (!NT_STATUS_IS_OK(status)) {
1768 reply_nterror(req, status);
1769 END_PROFILE(SMBopenX);
1773 if (!map_open_params_to_ntcreate(
1774 fname, deny_mode, smb_ofun, &access_mask,
1775 &share_mode, &create_disposition, &create_options)) {
1776 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1777 END_PROFILE(SMBopenX);
1781 status = SMB_VFS_CREATE_FILE(
1784 0, /* root_dir_fid */
1786 CFF_DOS_PATH, /* create_file_flags */
1787 access_mask, /* access_mask */
1788 share_mode, /* share_access */
1789 create_disposition, /* create_disposition*/
1790 create_options, /* create_options */
1791 smb_attr, /* file_attributes */
1792 oplock_request, /* oplock_request */
1793 0, /* allocation_size */
1797 &smb_action, /* pinfo */
1800 if (!NT_STATUS_IS_OK(status)) {
1801 END_PROFILE(SMBopenX);
1802 if (open_was_deferred(req->mid)) {
1803 /* We have re-scheduled this call. */
1806 reply_openerror(req, status);
1810 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1811 if the file is truncated or created. */
1812 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1813 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1814 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1815 close_file(req, fsp, ERROR_CLOSE);
1816 reply_nterror(req, NT_STATUS_DISK_FULL);
1817 END_PROFILE(SMBopenX);
1820 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1822 close_file(req, fsp, ERROR_CLOSE);
1823 reply_nterror(req, NT_STATUS_DISK_FULL);
1824 END_PROFILE(SMBopenX);
1827 sbuf.st_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
1830 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1831 mtime = sbuf.st_mtime;
1833 close_file(req, fsp, ERROR_CLOSE);
1834 reply_doserror(req, ERRDOS, ERRnoaccess);
1835 END_PROFILE(SMBopenX);
1839 /* If the caller set the extended oplock request bit
1840 and we granted one (by whatever means) - set the
1841 correct bit for extended oplock reply.
1844 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1845 smb_action |= EXTENDED_OPLOCK_GRANTED;
1848 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1849 smb_action |= EXTENDED_OPLOCK_GRANTED;
1852 /* If the caller set the core oplock request bit
1853 and we granted one (by whatever means) - set the
1854 correct bit for core oplock reply.
1857 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1858 reply_outbuf(req, 19, 0);
1860 reply_outbuf(req, 15, 0);
1863 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1864 SCVAL(req->outbuf, smb_flg,
1865 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1868 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1869 SCVAL(req->outbuf, smb_flg,
1870 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1873 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1874 SSVAL(req->outbuf,smb_vwv3,fattr);
1875 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1876 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1878 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1880 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1881 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1882 SSVAL(req->outbuf,smb_vwv11,smb_action);
1884 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1885 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1888 END_PROFILE(SMBopenX);
1893 /****************************************************************************
1894 Reply to a SMBulogoffX.
1895 ****************************************************************************/
1897 void reply_ulogoffX(struct smb_request *req)
1901 START_PROFILE(SMBulogoffX);
1903 vuser = get_valid_user_struct(req->vuid);
1906 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1910 /* in user level security we are supposed to close any files
1911 open by this user */
1912 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1913 file_close_user(req->vuid);
1916 invalidate_vuid(req->vuid);
1918 reply_outbuf(req, 2, 0);
1920 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1922 END_PROFILE(SMBulogoffX);
1926 /****************************************************************************
1927 Reply to a mknew or a create.
1928 ****************************************************************************/
1930 void reply_mknew(struct smb_request *req)
1932 connection_struct *conn = req->conn;
1935 struct smb_file_time ft;
1937 int oplock_request = 0;
1938 SMB_STRUCT_STAT sbuf;
1940 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1941 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1942 uint32 create_disposition;
1943 uint32 create_options = 0;
1944 TALLOC_CTX *ctx = talloc_tos();
1946 START_PROFILE(SMBcreate);
1950 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1951 END_PROFILE(SMBcreate);
1955 fattr = SVAL(req->vwv+0, 0);
1956 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1959 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
1961 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
1962 STR_TERMINATE, &status);
1963 if (!NT_STATUS_IS_OK(status)) {
1964 reply_nterror(req, status);
1965 END_PROFILE(SMBcreate);
1969 if (fattr & aVOLID) {
1970 DEBUG(0,("Attempt to create file (%s) with volid set - "
1971 "please report this\n", fname));
1974 if(req->cmd == SMBmknew) {
1975 /* We should fail if file exists. */
1976 create_disposition = FILE_CREATE;
1978 /* Create if file doesn't exist, truncate if it does. */
1979 create_disposition = FILE_OVERWRITE_IF;
1982 status = SMB_VFS_CREATE_FILE(
1985 0, /* root_dir_fid */
1987 CFF_DOS_PATH, /* create_file_flags */
1988 access_mask, /* access_mask */
1989 share_mode, /* share_access */
1990 create_disposition, /* create_disposition*/
1991 create_options, /* create_options */
1992 fattr, /* file_attributes */
1993 oplock_request, /* oplock_request */
1994 0, /* allocation_size */
2001 if (!NT_STATUS_IS_OK(status)) {
2002 END_PROFILE(SMBcreate);
2003 if (open_was_deferred(req->mid)) {
2004 /* We have re-scheduled this call. */
2007 reply_openerror(req, status);
2011 ft.atime = get_atimespec(&sbuf); /* atime. */
2012 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true);
2013 if (!NT_STATUS_IS_OK(status)) {
2014 END_PROFILE(SMBcreate);
2015 reply_openerror(req, status);
2019 reply_outbuf(req, 1, 0);
2020 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2022 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2023 SCVAL(req->outbuf,smb_flg,
2024 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2027 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2028 SCVAL(req->outbuf,smb_flg,
2029 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2032 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2033 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2034 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2036 END_PROFILE(SMBcreate);
2040 /****************************************************************************
2041 Reply to a create temporary file.
2042 ****************************************************************************/
2044 void reply_ctemp(struct smb_request *req)
2046 connection_struct *conn = req->conn;
2052 SMB_STRUCT_STAT sbuf;
2055 TALLOC_CTX *ctx = talloc_tos();
2057 START_PROFILE(SMBctemp);
2060 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2061 END_PROFILE(SMBctemp);
2065 fattr = SVAL(req->vwv+0, 0);
2066 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2068 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2069 STR_TERMINATE, &status);
2070 if (!NT_STATUS_IS_OK(status)) {
2071 reply_nterror(req, status);
2072 END_PROFILE(SMBctemp);
2076 fname = talloc_asprintf(ctx,
2080 fname = talloc_strdup(ctx, "TMXXXXXX");
2084 reply_nterror(req, NT_STATUS_NO_MEMORY);
2085 END_PROFILE(SMBctemp);
2089 status = resolve_dfspath(ctx, conn,
2090 req->flags2 & FLAGS2_DFS_PATHNAMES,
2093 if (!NT_STATUS_IS_OK(status)) {
2094 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2095 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2096 ERRSRV, ERRbadpath);
2097 END_PROFILE(SMBctemp);
2100 reply_nterror(req, status);
2101 END_PROFILE(SMBctemp);
2105 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
2106 if (!NT_STATUS_IS_OK(status)) {
2107 reply_nterror(req, status);
2108 END_PROFILE(SMBctemp);
2112 status = check_name(conn, fname);
2113 if (!NT_STATUS_IS_OK(status)) {
2114 reply_nterror(req, status);
2115 END_PROFILE(SMBctemp);
2119 tmpfd = smb_mkstemp(fname);
2121 reply_unixerror(req, ERRDOS, ERRnoaccess);
2122 END_PROFILE(SMBctemp);
2126 SMB_VFS_STAT(conn,fname,&sbuf);
2128 /* We should fail if file does not exist. */
2129 status = SMB_VFS_CREATE_FILE(
2132 0, /* root_dir_fid */
2134 0, /* create_file_flags */
2135 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2136 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2137 FILE_OPEN, /* create_disposition*/
2138 0, /* create_options */
2139 fattr, /* file_attributes */
2140 oplock_request, /* oplock_request */
2141 0, /* allocation_size */
2148 /* close fd from smb_mkstemp() */
2151 if (!NT_STATUS_IS_OK(status)) {
2152 if (open_was_deferred(req->mid)) {
2153 /* We have re-scheduled this call. */
2154 END_PROFILE(SMBctemp);
2157 reply_openerror(req, status);
2158 END_PROFILE(SMBctemp);
2162 reply_outbuf(req, 1, 0);
2163 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2165 /* the returned filename is relative to the directory */
2166 s = strrchr_m(fsp->fsp_name, '/');
2174 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2175 thing in the byte section. JRA */
2176 SSVALS(p, 0, -1); /* what is this? not in spec */
2178 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2180 reply_nterror(req, NT_STATUS_NO_MEMORY);
2181 END_PROFILE(SMBctemp);
2185 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2186 SCVAL(req->outbuf, smb_flg,
2187 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2190 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2191 SCVAL(req->outbuf, smb_flg,
2192 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2195 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2196 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2197 fsp->fh->fd, (unsigned int)sbuf.st_mode ) );
2199 END_PROFILE(SMBctemp);
2203 /*******************************************************************
2204 Check if a user is allowed to rename a file.
2205 ********************************************************************/
2207 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2208 uint16 dirtype, SMB_STRUCT_STAT *pst)
2212 if (!CAN_WRITE(conn)) {
2213 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2216 fmode = dos_mode(conn, fsp->fsp_name, pst);
2217 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2218 return NT_STATUS_NO_SUCH_FILE;
2221 if (S_ISDIR(pst->st_mode)) {
2222 if (fsp->posix_open) {
2223 return NT_STATUS_OK;
2226 /* If no pathnames are open below this
2227 directory, allow the rename. */
2229 if (file_find_subpath(fsp)) {
2230 return NT_STATUS_ACCESS_DENIED;
2232 return NT_STATUS_OK;
2235 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2236 return NT_STATUS_OK;
2239 return NT_STATUS_ACCESS_DENIED;
2242 /*******************************************************************
2243 * unlink a file with all relevant access checks
2244 *******************************************************************/
2246 static NTSTATUS do_unlink(connection_struct *conn,
2247 struct smb_request *req,
2251 SMB_STRUCT_STAT sbuf;
2254 uint32 dirtype_orig = dirtype;
2257 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2259 if (!CAN_WRITE(conn)) {
2260 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2263 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2264 return map_nt_error_from_unix(errno);
2267 fattr = dos_mode(conn,fname,&sbuf);
2269 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2270 dirtype = aDIR|aARCH|aRONLY;
2273 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2275 return NT_STATUS_NO_SUCH_FILE;
2278 if (!dir_check_ftype(conn, fattr, dirtype)) {
2280 return NT_STATUS_FILE_IS_A_DIRECTORY;
2282 return NT_STATUS_NO_SUCH_FILE;
2285 if (dirtype_orig & 0x8000) {
2286 /* These will never be set for POSIX. */
2287 return NT_STATUS_NO_SUCH_FILE;
2291 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2292 return NT_STATUS_FILE_IS_A_DIRECTORY;
2295 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2296 return NT_STATUS_NO_SUCH_FILE;
2299 if (dirtype & 0xFF00) {
2300 /* These will never be set for POSIX. */
2301 return NT_STATUS_NO_SUCH_FILE;
2306 return NT_STATUS_NO_SUCH_FILE;
2309 /* Can't delete a directory. */
2311 return NT_STATUS_FILE_IS_A_DIRECTORY;
2316 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2317 return NT_STATUS_OBJECT_NAME_INVALID;
2318 #endif /* JRATEST */
2320 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2322 On a Windows share, a file with read-only dosmode can be opened with
2323 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2324 fails with NT_STATUS_CANNOT_DELETE error.
2326 This semantic causes a problem that a user can not
2327 rename a file with read-only dosmode on a Samba share
2328 from a Windows command prompt (i.e. cmd.exe, but can rename
2329 from Windows Explorer).
2332 if (!lp_delete_readonly(SNUM(conn))) {
2333 if (fattr & aRONLY) {
2334 return NT_STATUS_CANNOT_DELETE;
2338 /* On open checks the open itself will check the share mode, so
2339 don't do it here as we'll get it wrong. */
2341 status = SMB_VFS_CREATE_FILE
2344 0, /* root_dir_fid */
2346 0, /* create_file_flags */
2347 DELETE_ACCESS, /* access_mask */
2348 FILE_SHARE_NONE, /* share_access */
2349 FILE_OPEN, /* create_disposition*/
2350 FILE_NON_DIRECTORY_FILE, /* create_options */
2351 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2352 0, /* oplock_request */
2353 0, /* allocation_size */
2360 if (!NT_STATUS_IS_OK(status)) {
2361 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2362 nt_errstr(status)));
2366 /* The set is across all open files on this dev/inode pair. */
2367 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2368 close_file(req, fsp, NORMAL_CLOSE);
2369 return NT_STATUS_ACCESS_DENIED;
2372 return close_file(req, fsp, NORMAL_CLOSE);
2375 /****************************************************************************
2376 The guts of the unlink command, split out so it may be called by the NT SMB
2378 ****************************************************************************/
2380 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2381 uint32 dirtype, const char *name_in, bool has_wild)
2383 const char *directory = NULL;
2388 NTSTATUS status = NT_STATUS_OK;
2389 SMB_STRUCT_STAT sbuf, st;
2390 TALLOC_CTX *ctx = talloc_tos();
2392 status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
2393 if (!NT_STATUS_IS_OK(status)) {
2397 p = strrchr_m(name,'/');
2399 directory = talloc_strdup(ctx, ".");
2401 return NT_STATUS_NO_MEMORY;
2411 * We should only check the mangled cache
2412 * here if unix_convert failed. This means
2413 * that the path in 'mask' doesn't exist
2414 * on the file system and so we need to look
2415 * for a possible mangle. This patch from
2416 * Tine Smukavec <valentin.smukavec@hermes.si>.
2419 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
2420 char *new_mask = NULL;
2421 mangle_lookup_name_from_8_3(ctx,
2431 directory = talloc_asprintf(ctx,
2436 return NT_STATUS_NO_MEMORY;
2439 dirtype = FILE_ATTRIBUTE_NORMAL;
2442 status = check_name(conn, directory);
2443 if (!NT_STATUS_IS_OK(status)) {
2447 status = do_unlink(conn, req, directory, dirtype);
2448 if (!NT_STATUS_IS_OK(status)) {
2454 struct smb_Dir *dir_hnd = NULL;
2458 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2459 return NT_STATUS_OBJECT_NAME_INVALID;
2462 if (strequal(mask,"????????.???")) {
2467 status = check_name(conn, directory);
2468 if (!NT_STATUS_IS_OK(status)) {
2472 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2474 if (dir_hnd == NULL) {
2475 return map_nt_error_from_unix(errno);
2478 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2479 the pattern matches against the long name, otherwise the short name
2480 We don't implement this yet XXXX
2483 status = NT_STATUS_NO_SUCH_FILE;
2485 while ((dname = ReadDirName(dir_hnd, &offset, &st))) {
2488 if (!is_visible_file(conn, directory, dname, &st,
2494 /* Quick check for "." and ".." */
2495 if (ISDOT(dname) || ISDOTDOT(dname)) {
2499 if(!mask_match(dname, mask, conn->case_sensitive)) {
2503 fname = talloc_asprintf(ctx, "%s/%s",
2507 return NT_STATUS_NO_MEMORY;
2510 status = check_name(conn, fname);
2511 if (!NT_STATUS_IS_OK(status)) {
2512 TALLOC_FREE(dir_hnd);
2516 status = do_unlink(conn, req, fname, dirtype);
2517 if (!NT_STATUS_IS_OK(status)) {
2523 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2528 TALLOC_FREE(dir_hnd);
2531 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2532 status = map_nt_error_from_unix(errno);
2538 /****************************************************************************
2540 ****************************************************************************/
2542 void reply_unlink(struct smb_request *req)
2544 connection_struct *conn = req->conn;
2548 bool path_contains_wcard = False;
2549 TALLOC_CTX *ctx = talloc_tos();
2551 START_PROFILE(SMBunlink);
2554 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2555 END_PROFILE(SMBunlink);
2559 dirtype = SVAL(req->vwv+0, 0);
2561 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2562 STR_TERMINATE, &status,
2563 &path_contains_wcard);
2564 if (!NT_STATUS_IS_OK(status)) {
2565 reply_nterror(req, status);
2566 END_PROFILE(SMBunlink);
2570 status = resolve_dfspath_wcard(ctx, conn,
2571 req->flags2 & FLAGS2_DFS_PATHNAMES,
2574 &path_contains_wcard);
2575 if (!NT_STATUS_IS_OK(status)) {
2576 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2577 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2578 ERRSRV, ERRbadpath);
2579 END_PROFILE(SMBunlink);
2582 reply_nterror(req, status);
2583 END_PROFILE(SMBunlink);
2587 DEBUG(3,("reply_unlink : %s\n",name));
2589 status = unlink_internals(conn, req, dirtype, name,
2590 path_contains_wcard);
2591 if (!NT_STATUS_IS_OK(status)) {
2592 if (open_was_deferred(req->mid)) {
2593 /* We have re-scheduled this call. */
2594 END_PROFILE(SMBunlink);
2597 reply_nterror(req, status);
2598 END_PROFILE(SMBunlink);
2602 reply_outbuf(req, 0, 0);
2603 END_PROFILE(SMBunlink);
2608 /****************************************************************************
2610 ****************************************************************************/
2612 static void fail_readraw(void)
2614 const char *errstr = talloc_asprintf(talloc_tos(),
2615 "FAIL ! reply_readbraw: socket write fail (%s)",
2620 exit_server_cleanly(errstr);
2623 /****************************************************************************
2624 Fake (read/write) sendfile. Returns -1 on read or write fail.
2625 ****************************************************************************/
2627 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2631 size_t tosend = nread;
2638 bufsize = MIN(nread, 65536);
2640 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2644 while (tosend > 0) {
2648 if (tosend > bufsize) {
2653 ret = read_file(fsp,buf,startpos,cur_read);
2659 /* If we had a short read, fill with zeros. */
2660 if (ret < cur_read) {
2661 memset(buf, '\0', cur_read - ret);
2664 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2669 startpos += cur_read;
2673 return (ssize_t)nread;
2676 /****************************************************************************
2677 Deal with the case of sendfile reading less bytes from the file than
2678 requested. Fill with zeros (all we can do).
2679 ****************************************************************************/
2681 static void sendfile_short_send(files_struct *fsp,
2686 if (nread < headersize) {
2687 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2688 "header for file %s (%s). Terminating\n",
2689 fsp->fsp_name, strerror(errno) ));
2690 exit_server_cleanly("sendfile_short_send failed");
2693 nread -= headersize;
2695 if (nread < smb_maxcnt) {
2696 char *buf = SMB_CALLOC_ARRAY(char, 1024);
2698 exit_server_cleanly("sendfile_short_send: "
2702 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2703 "with zeros !\n", fsp->fsp_name));
2705 while (nread < smb_maxcnt) {
2707 * We asked for the real file size and told sendfile
2708 * to not go beyond the end of the file. But it can
2709 * happen that in between our fstat call and the
2710 * sendfile call the file was truncated. This is very
2711 * bad because we have already announced the larger
2712 * number of bytes to the client.
2714 * The best we can do now is to send 0-bytes, just as
2715 * a read from a hole in a sparse file would do.
2717 * This should happen rarely enough that I don't care
2718 * about efficiency here :-)
2722 to_write = MIN(sizeof(buf), smb_maxcnt - nread);
2723 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2724 exit_server_cleanly("sendfile_short_send: "
2725 "write_data failed");
2733 /****************************************************************************
2734 Return a readbraw error (4 bytes of zero).
2735 ****************************************************************************/
2737 static void reply_readbraw_error(void)
2741 if (write_data(smbd_server_fd(),header,4) != 4) {
2746 /****************************************************************************
2747 Use sendfile in readbraw.
2748 ****************************************************************************/
2750 static void send_file_readbraw(connection_struct *conn,
2751 struct smb_request *req,
2757 char *outbuf = NULL;
2760 #if defined(WITH_SENDFILE)
2762 * We can only use sendfile on a non-chained packet
2763 * but we can use on a non-oplocked file. tridge proved this
2764 * on a train in Germany :-). JRA.
2765 * reply_readbraw has already checked the length.
2768 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2769 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2770 ssize_t sendfile_read = -1;
2772 DATA_BLOB header_blob;
2774 _smb_setlen(header,nread);
2775 header_blob = data_blob_const(header, 4);
2777 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2778 &header_blob, startpos, nread)) == -1) {
2779 /* Returning ENOSYS means no data at all was sent.
2780 * Do this as a normal read. */
2781 if (errno == ENOSYS) {
2782 goto normal_readbraw;
2786 * Special hack for broken Linux with no working sendfile. If we
2787 * return EINTR we sent the header but not the rest of the data.
2788 * Fake this up by doing read/write calls.
2790 if (errno == EINTR) {
2791 /* Ensure we don't do this again. */
2792 set_use_sendfile(SNUM(conn), False);
2793 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2795 if (fake_sendfile(fsp, startpos, nread) == -1) {
2796 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2797 fsp->fsp_name, strerror(errno) ));
2798 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2803 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2804 fsp->fsp_name, strerror(errno) ));
2805 exit_server_cleanly("send_file_readbraw sendfile failed");
2806 } else if (sendfile_read == 0) {
2808 * Some sendfile implementations return 0 to indicate
2809 * that there was a short read, but nothing was
2810 * actually written to the socket. In this case,
2811 * fallback to the normal read path so the header gets
2812 * the correct byte count.
2814 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2815 "bytes falling back to the normal read: "
2816 "%s\n", fsp->fsp_name));
2817 goto normal_readbraw;
2820 /* Deal with possible short send. */
2821 if (sendfile_read != 4+nread) {
2822 sendfile_short_send(fsp, sendfile_read, 4, nread);
2830 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2832 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2833 (unsigned)(nread+4)));
2834 reply_readbraw_error();
2839 ret = read_file(fsp,outbuf+4,startpos,nread);
2840 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2849 _smb_setlen(outbuf,ret);
2850 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2853 TALLOC_FREE(outbuf);
2856 /****************************************************************************
2857 Reply to a readbraw (core+ protocol).
2858 ****************************************************************************/
2860 void reply_readbraw(struct smb_request *req)
2862 connection_struct *conn = req->conn;
2863 ssize_t maxcount,mincount;
2867 struct lock_struct lock;
2871 START_PROFILE(SMBreadbraw);
2873 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
2874 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2875 "raw reads/writes are disallowed.");
2879 reply_readbraw_error();
2880 END_PROFILE(SMBreadbraw);
2885 * Special check if an oplock break has been issued
2886 * and the readraw request croses on the wire, we must
2887 * return a zero length response here.
2890 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2893 * We have to do a check_fsp by hand here, as
2894 * we must always return 4 zero bytes on error,
2898 if (!fsp || !conn || conn != fsp->conn ||
2899 req->vuid != fsp->vuid ||
2900 fsp->is_directory || fsp->fh->fd == -1) {
2902 * fsp could be NULL here so use the value from the packet. JRA.
2904 DEBUG(3,("reply_readbraw: fnum %d not valid "
2906 (int)SVAL(req->vwv+0, 0)));
2907 reply_readbraw_error();
2908 END_PROFILE(SMBreadbraw);
2912 /* Do a "by hand" version of CHECK_READ. */
2913 if (!(fsp->can_read ||
2914 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2915 (fsp->access_mask & FILE_EXECUTE)))) {
2916 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2917 (int)SVAL(req->vwv+0, 0)));
2918 reply_readbraw_error();
2919 END_PROFILE(SMBreadbraw);
2923 flush_write_cache(fsp, READRAW_FLUSH);
2925 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
2926 if(req->wct == 10) {
2928 * This is a large offset (64 bit) read.
2930 #ifdef LARGE_SMB_OFF_T
2932 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
2934 #else /* !LARGE_SMB_OFF_T */
2937 * Ensure we haven't been sent a >32 bit offset.
2940 if(IVAL(req->vwv+8, 0) != 0) {
2941 DEBUG(0,("reply_readbraw: large offset "
2942 "(%x << 32) used and we don't support "
2943 "64 bit offsets.\n",
2944 (unsigned int)IVAL(req->vwv+8, 0) ));
2945 reply_readbraw_error();
2946 END_PROFILE(SMBreadbraw);
2950 #endif /* LARGE_SMB_OFF_T */
2953 DEBUG(0,("reply_readbraw: negative 64 bit "
2954 "readraw offset (%.0f) !\n",
2955 (double)startpos ));
2956 reply_readbraw_error();
2957 END_PROFILE(SMBreadbraw);
2962 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
2963 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
2965 /* ensure we don't overrun the packet size */
2966 maxcount = MIN(65535,maxcount);
2968 init_strict_lock_struct(fsp, (uint32)req->smbpid,
2969 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
2972 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
2973 reply_readbraw_error();
2974 END_PROFILE(SMBreadbraw);
2978 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
2982 if (startpos >= size) {
2985 nread = MIN(maxcount,(size - startpos));
2988 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2989 if (nread < mincount)
2993 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2994 "min=%lu nread=%lu\n",
2995 fsp->fnum, (double)startpos,
2996 (unsigned long)maxcount,
2997 (unsigned long)mincount,
2998 (unsigned long)nread ) );
3000 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3002 DEBUG(5,("reply_readbraw finished\n"));
3004 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3006 END_PROFILE(SMBreadbraw);
3011 #define DBGC_CLASS DBGC_LOCKING
3013 /****************************************************************************
3014 Reply to a lockread (core+ protocol).
3015 ****************************************************************************/
3017 void reply_lockread(struct smb_request *req)
3019 connection_struct *conn = req->conn;
3026 struct byte_range_lock *br_lck = NULL;
3029 START_PROFILE(SMBlockread);
3032 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3033 END_PROFILE(SMBlockread);
3037 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3039 if (!check_fsp(conn, req, fsp)) {
3040 END_PROFILE(SMBlockread);
3044 if (!CHECK_READ(fsp,req)) {
3045 reply_doserror(req, ERRDOS, ERRbadaccess);
3046 END_PROFILE(SMBlockread);
3050 numtoread = SVAL(req->vwv+1, 0);
3051 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3053 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3055 reply_outbuf(req, 5, numtoread + 3);
3057 data = smb_buf(req->outbuf) + 3;
3060 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3061 * protocol request that predates the read/write lock concept.
3062 * Thus instead of asking for a read lock here we need to ask
3063 * for a write lock. JRA.
3064 * Note that the requested lock size is unaffected by max_recv.
3067 br_lck = do_lock(smbd_messaging_context(),
3070 (uint64_t)numtoread,
3074 False, /* Non-blocking lock. */
3078 TALLOC_FREE(br_lck);
3080 if (NT_STATUS_V(status)) {
3081 reply_nterror(req, status);
3082 END_PROFILE(SMBlockread);
3087 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3090 if (numtoread > max_recv) {
3091 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3092 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3093 (unsigned int)numtoread, (unsigned int)max_recv ));
3094 numtoread = MIN(numtoread,max_recv);
3096 nread = read_file(fsp,data,startpos,numtoread);
3099 reply_unixerror(req, ERRDOS, ERRnoaccess);
3100 END_PROFILE(SMBlockread);
3104 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3106 SSVAL(req->outbuf,smb_vwv0,nread);
3107 SSVAL(req->outbuf,smb_vwv5,nread+3);
3108 p = smb_buf(req->outbuf);
3109 SCVAL(p,0,0); /* pad byte. */
3112 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3113 fsp->fnum, (int)numtoread, (int)nread));
3115 END_PROFILE(SMBlockread);
3120 #define DBGC_CLASS DBGC_ALL
3122 /****************************************************************************
3124 ****************************************************************************/
3126 void reply_read(struct smb_request *req)
3128 connection_struct *conn = req->conn;
3135 struct lock_struct lock;
3137 START_PROFILE(SMBread);
3140 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3141 END_PROFILE(SMBread);
3145 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3147 if (!check_fsp(conn, req, fsp)) {
3148 END_PROFILE(SMBread);
3152 if (!CHECK_READ(fsp,req)) {
3153 reply_doserror(req, ERRDOS, ERRbadaccess);
3154 END_PROFILE(SMBread);
3158 numtoread = SVAL(req->vwv+1, 0);
3159 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3161 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3164 * The requested read size cannot be greater than max_recv. JRA.
3166 if (numtoread > max_recv) {
3167 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3168 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3169 (unsigned int)numtoread, (unsigned int)max_recv ));
3170 numtoread = MIN(numtoread,max_recv);
3173 reply_outbuf(req, 5, numtoread+3);
3175 data = smb_buf(req->outbuf) + 3;
3177 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3178 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3181 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3182 reply_doserror(req, ERRDOS,ERRlock);
3183 END_PROFILE(SMBread);
3188 nread = read_file(fsp,data,startpos,numtoread);
3191 reply_unixerror(req, ERRDOS,ERRnoaccess);
3195 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3197 SSVAL(req->outbuf,smb_vwv0,nread);
3198 SSVAL(req->outbuf,smb_vwv5,nread+3);
3199 SCVAL(smb_buf(req->outbuf),0,1);
3200 SSVAL(smb_buf(req->outbuf),1,nread);
3202 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3203 fsp->fnum, (int)numtoread, (int)nread ) );
3206 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3208 END_PROFILE(SMBread);
3212 /****************************************************************************
3214 ****************************************************************************/
3216 static int setup_readX_header(struct smb_request *req, char *outbuf,
3222 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3223 data = smb_buf(outbuf);
3225 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3227 SCVAL(outbuf,smb_vwv0,0xFF);
3228 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3229 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3230 SSVAL(outbuf,smb_vwv6,
3232 + 1 /* the wct field */
3233 + 12 * sizeof(uint16_t) /* vwv */
3234 + 2); /* the buflen field */
3235 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3236 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3237 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3238 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3242 /****************************************************************************
3243 Reply to a read and X - possibly using sendfile.
3244 ****************************************************************************/
3246 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3247 files_struct *fsp, SMB_OFF_T startpos,
3250 SMB_STRUCT_STAT sbuf;
3253 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3254 reply_unixerror(req, ERRDOS, ERRnoaccess);
3258 if (startpos > sbuf.st_size) {
3260 } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
3261 smb_maxcnt = (sbuf.st_size - startpos);
3264 if (smb_maxcnt == 0) {
3268 #if defined(WITH_SENDFILE)
3270 * We can only use sendfile on a non-chained packet
3271 * but we can use on a non-oplocked file. tridge proved this
3272 * on a train in Germany :-). JRA.
3275 if (!req_is_in_chain(req) &&
3276 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3277 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
3278 uint8 headerbuf[smb_size + 12 * 2];
3282 * Set up the packet header before send. We
3283 * assume here the sendfile will work (get the
3284 * correct amount of data).
3287 header = data_blob_const(headerbuf, sizeof(headerbuf));
3289 construct_reply_common_req(req, (char *)headerbuf);
3290 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3292 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3293 /* Returning ENOSYS means no data at all was sent.
3294 Do this as a normal read. */
3295 if (errno == ENOSYS) {
3300 * Special hack for broken Linux with no working sendfile. If we
3301 * return EINTR we sent the header but not the rest of the data.
3302 * Fake this up by doing read/write calls.
3305 if (errno == EINTR) {
3306 /* Ensure we don't do this again. */
3307 set_use_sendfile(SNUM(conn), False);
3308 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3309 nread = fake_sendfile(fsp, startpos,
3312 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3313 fsp->fsp_name, strerror(errno) ));
3314 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3316 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3317 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3318 /* No outbuf here means successful sendfile. */
3319 TALLOC_FREE(req->outbuf);
3323 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3324 fsp->fsp_name, strerror(errno) ));
3325 exit_server_cleanly("send_file_readX sendfile failed");
3326 } else if (nread == 0) {
3328 * Some sendfile implementations return 0 to indicate
3329 * that there was a short read, but nothing was
3330 * actually written to the socket. In this case,
3331 * fallback to the normal read path so the header gets
3332 * the correct byte count.
3334 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3335 "falling back to the normal read: %s\n",
3340 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3341 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3343 /* Deal with possible short send. */
3344 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3345 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3348 /* No outbuf here means successful sendfile. */
3349 TALLOC_FREE(req->outbuf);
3350 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3351 SMB_PERFCOUNT_END(&req->pcd);
3358 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3359 uint8 headerbuf[smb_size + 2*12];
3361 construct_reply_common_req(req, (char *)headerbuf);
3362 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3364 /* Send out the header. */
3365 if (write_data(smbd_server_fd(), (char *)headerbuf,
3366 sizeof(headerbuf)) != sizeof(headerbuf)) {
3367 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3368 fsp->fsp_name, strerror(errno) ));
3369 exit_server_cleanly("send_file_readX sendfile failed");
3371 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3373 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3374 fsp->fsp_name, strerror(errno) ));
3375 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3377 TALLOC_FREE(req->outbuf);
3381 reply_outbuf(req, 12, smb_maxcnt);
3383 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3385 reply_unixerror(req, ERRDOS, ERRnoaccess);
3389 setup_readX_header(req, (char *)req->outbuf, nread);
3391 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3392 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3397 /****************************************************************************
3398 Reply to a read and X.
3399 ****************************************************************************/
3401 void reply_read_and_X(struct smb_request *req)
3403 connection_struct *conn = req->conn;
3407 struct lock_struct lock;
3408 bool big_readX = False;
3410 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3413 START_PROFILE(SMBreadX);
3415 if ((req->wct != 10) && (req->wct != 12)) {
3416 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3420 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3421 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3422 smb_maxcnt = SVAL(req->vwv+5, 0);
3424 /* If it's an IPC, pass off the pipe handler. */
3426 reply_pipe_read_and_X(req);
3427 END_PROFILE(SMBreadX);
3431 if (!check_fsp(conn, req, fsp)) {
3432 END_PROFILE(SMBreadX);
3436 if (!CHECK_READ(fsp,req)) {
3437 reply_doserror(req, ERRDOS,ERRbadaccess);
3438 END_PROFILE(SMBreadX);
3442 if (global_client_caps & CAP_LARGE_READX) {
3443 size_t upper_size = SVAL(req->vwv+7, 0);
3444 smb_maxcnt |= (upper_size<<16);
3445 if (upper_size > 1) {
3446 /* Can't do this on a chained packet. */
3447 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3448 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3449 END_PROFILE(SMBreadX);
3452 /* We currently don't do this on signed or sealed data. */
3453 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
3454 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3455 END_PROFILE(SMBreadX);
3458 /* Is there room in the reply for this data ? */
3459 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3461 NT_STATUS_INVALID_PARAMETER);
3462 END_PROFILE(SMBreadX);
3469 if (req->wct == 12) {
3470 #ifdef LARGE_SMB_OFF_T
3472 * This is a large offset (64 bit) read.
3474 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3476 #else /* !LARGE_SMB_OFF_T */
3479 * Ensure we haven't been sent a >32 bit offset.
3482 if(IVAL(req->vwv+10, 0) != 0) {
3483 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3484 "used and we don't support 64 bit offsets.\n",
3485 (unsigned int)IVAL(req->vwv+10, 0) ));
3486 END_PROFILE(SMBreadX);
3487 reply_doserror(req, ERRDOS, ERRbadaccess);
3491 #endif /* LARGE_SMB_OFF_T */
3495 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3496 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3499 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3500 END_PROFILE(SMBreadX);
3501 reply_doserror(req, ERRDOS, ERRlock);
3506 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3510 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3513 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3515 END_PROFILE(SMBreadX);
3519 /****************************************************************************
3520 Error replies to writebraw must have smb_wct == 1. Fix this up.
3521 ****************************************************************************/
3523 void error_to_writebrawerr(struct smb_request *req)
3525 uint8 *old_outbuf = req->outbuf;
3527 reply_outbuf(req, 1, 0);
3529 memcpy(req->outbuf, old_outbuf, smb_size);
3530 TALLOC_FREE(old_outbuf);
3533 /****************************************************************************
3534 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3535 ****************************************************************************/
3537 void reply_writebraw(struct smb_request *req)
3539 connection_struct *conn = req->conn;
3542 ssize_t total_written=0;
3543 size_t numtowrite=0;
3549 struct lock_struct lock;
3552 START_PROFILE(SMBwritebraw);
3555 * If we ever reply with an error, it must have the SMB command
3556 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3559 SCVAL(req->inbuf,smb_com,SMBwritec);
3561 if (srv_is_signing_active()) {
3562 END_PROFILE(SMBwritebraw);
3563 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3564 "raw reads/writes are disallowed.");
3567 if (req->wct < 12) {
3568 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3569 error_to_writebrawerr(req);
3570 END_PROFILE(SMBwritebraw);
3574 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3575 if (!check_fsp(conn, req, fsp)) {
3576 error_to_writebrawerr(req);
3577 END_PROFILE(SMBwritebraw);
3581 if (!CHECK_WRITE(fsp)) {
3582 reply_doserror(req, ERRDOS, ERRbadaccess);
3583 error_to_writebrawerr(req);
3584 END_PROFILE(SMBwritebraw);
3588 tcount = IVAL(req->vwv+1, 0);
3589 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3590 write_through = BITSETW(req->vwv+7,0);
3592 /* We have to deal with slightly different formats depending
3593 on whether we are using the core+ or lanman1.0 protocol */
3595 if(Protocol <= PROTOCOL_COREPLUS) {
3596 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3597 data = smb_buf(req->inbuf);
3599 numtowrite = SVAL(req->vwv+10, 0);
3600 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3603 /* Ensure we don't write bytes past the end of this packet. */
3604 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3605 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3606 error_to_writebrawerr(req);
3607 END_PROFILE(SMBwritebraw);
3611 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3612 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3615 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3616 reply_doserror(req, ERRDOS, ERRlock);
3617 error_to_writebrawerr(req);
3618 END_PROFILE(SMBwritebraw);
3623 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3626 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3627 "wrote=%d sync=%d\n",
3628 fsp->fnum, (double)startpos, (int)numtowrite,
3629 (int)nwritten, (int)write_through));
3631 if (nwritten < (ssize_t)numtowrite) {
3632 reply_unixerror(req, ERRHRD, ERRdiskfull);
3633 error_to_writebrawerr(req);
3637 total_written = nwritten;
3639 /* Allocate a buffer of 64k + length. */
3640 buf = TALLOC_ARRAY(NULL, char, 65540);
3642 reply_doserror(req, ERRDOS, ERRnomem);
3643 error_to_writebrawerr(req);
3647 /* Return a SMBwritebraw message to the redirector to tell
3648 * it to send more bytes */
3650 memcpy(buf, req->inbuf, smb_size);
3651 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3652 SCVAL(buf,smb_com,SMBwritebraw);
3653 SSVALS(buf,smb_vwv0,0xFFFF);
3655 if (!srv_send_smb(smbd_server_fd(),
3657 IS_CONN_ENCRYPTED(conn),
3659 exit_server_cleanly("reply_writebraw: srv_send_smb "
3663 /* Now read the raw data into the buffer and write it */
3664 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3666 if (!NT_STATUS_IS_OK(status)) {
3667 exit_server_cleanly("secondary writebraw failed");
3670 /* Set up outbuf to return the correct size */
3671 reply_outbuf(req, 1, 0);
3673 if (numtowrite != 0) {
3675 if (numtowrite > 0xFFFF) {
3676 DEBUG(0,("reply_writebraw: Oversize secondary write "
3677 "raw requested (%u). Terminating\n",
3678 (unsigned int)numtowrite ));
3679 exit_server_cleanly("secondary writebraw failed");
3682 if (tcount > nwritten+numtowrite) {
3683 DEBUG(3,("reply_writebraw: Client overestimated the "
3685 (int)tcount,(int)nwritten,(int)numtowrite));
3688 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3690 if (!NT_STATUS_IS_OK(status)) {
3691 DEBUG(0,("reply_writebraw: Oversize secondary write "
3692 "raw read failed (%s). Terminating\n",
3693 nt_errstr(status)));
3694 exit_server_cleanly("secondary writebraw failed");
3697 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3698 if (nwritten == -1) {
3700 reply_unixerror(req, ERRHRD, ERRdiskfull);
3701 error_to_writebrawerr(req);
3705 if (nwritten < (ssize_t)numtowrite) {
3706 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3707 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3711 total_written += nwritten;
3716 SSVAL(req->outbuf,smb_vwv0,total_written);
3718 status = sync_file(conn, fsp, write_through);
3719 if (!NT_STATUS_IS_OK(status)) {
3720 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3721 fsp->fsp_name, nt_errstr(status) ));
3722 reply_nterror(req, status);
3723 error_to_writebrawerr(req);
3727 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3729 fsp->fnum, (double)startpos, (int)numtowrite,
3730 (int)total_written));
3732 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3734 /* We won't return a status if write through is not selected - this
3735 * follows what WfWg does */
3736 END_PROFILE(SMBwritebraw);
3738 if (!write_through && total_written==tcount) {
3740 #if RABBIT_PELLET_FIX
3742 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3743 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3746 if (!send_keepalive(smbd_server_fd())) {
3747 exit_server_cleanly("reply_writebraw: send of "
3748 "keepalive failed");
3751 TALLOC_FREE(req->outbuf);
3756 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3758 END_PROFILE(SMBwritebraw);
3763 #define DBGC_CLASS DBGC_LOCKING
3765 /****************************************************************************
3766 Reply to a writeunlock (core+).
3767 ****************************************************************************/
3769 void reply_writeunlock(struct smb_request *req)
3771 connection_struct *conn = req->conn;
3772 ssize_t nwritten = -1;
3776 NTSTATUS status = NT_STATUS_OK;
3778 struct lock_struct lock;
3780 START_PROFILE(SMBwriteunlock);
3783 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3784 END_PROFILE(SMBwriteunlock);
3788 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3790 if (!check_fsp(conn, req, fsp)) {
3791 END_PROFILE(SMBwriteunlock);
3795 if (!CHECK_WRITE(fsp)) {
3796 reply_doserror(req, ERRDOS,ERRbadaccess);
3797 END_PROFILE(SMBwriteunlock);
3801 numtowrite = SVAL(req->vwv+1, 0);
3802 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3803 data = (const char *)req->buf + 3;
3806 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3807 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3810 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3811 reply_doserror(req, ERRDOS, ERRlock);
3812 END_PROFILE(SMBwriteunlock);
3817 /* The special X/Open SMB protocol handling of
3818 zero length writes is *NOT* done for
3820 if(numtowrite == 0) {
3823 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3826 status = sync_file(conn, fsp, False /* write through */);
3827 if (!NT_STATUS_IS_OK(status)) {
3828 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3829 fsp->fsp_name, nt_errstr(status) ));
3830 reply_nterror(req, status);
3834 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3835 reply_unixerror(req, ERRHRD, ERRdiskfull);
3840 status = do_unlock(smbd_messaging_context(),
3843 (uint64_t)numtowrite,
3847 if (NT_STATUS_V(status)) {
3848 reply_nterror(req, status);
3853 reply_outbuf(req, 1, 0);
3855 SSVAL(req->outbuf,smb_vwv0,nwritten);
3857 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3858 fsp->fnum, (int)numtowrite, (int)nwritten));
3862 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3865 END_PROFILE(SMBwriteunlock);
3870 #define DBGC_CLASS DBGC_ALL
3872 /****************************************************************************
3874 ****************************************************************************/
3876 void reply_write(struct smb_request *req)
3878 connection_struct *conn = req->conn;
3880 ssize_t nwritten = -1;
3884 struct lock_struct lock;
3887 START_PROFILE(SMBwrite);
3890 END_PROFILE(SMBwrite);
3891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3895 /* If it's an IPC, pass off the pipe handler. */
3897 reply_pipe_write(req);
3898 END_PROFILE(SMBwrite);
3902 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3904 if (!check_fsp(conn, req, fsp)) {
3905 END_PROFILE(SMBwrite);
3909 if (!CHECK_WRITE(fsp)) {
3910 reply_doserror(req, ERRDOS, ERRbadaccess);
3911 END_PROFILE(SMBwrite);
3915 numtowrite = SVAL(req->vwv+1, 0);
3916 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3917 data = (const char *)req->buf + 3;
3919 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3920 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3923 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3924 reply_doserror(req, ERRDOS, ERRlock);
3925 END_PROFILE(SMBwrite);
3930 * X/Open SMB protocol says that if smb_vwv1 is
3931 * zero then the file size should be extended or
3932 * truncated to the size given in smb_vwv[2-3].
3935 if(numtowrite == 0) {
3937 * This is actually an allocate call, and set EOF. JRA.
3939 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3941 reply_nterror(req, NT_STATUS_DISK_FULL);
3944 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3946 reply_nterror(req, NT_STATUS_DISK_FULL);
3949 trigger_write_time_update_immediate(fsp);
3951 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3954 status = sync_file(conn, fsp, False);
3955 if (!NT_STATUS_IS_OK(status)) {
3956 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3957 fsp->fsp_name, nt_errstr(status) ));
3958 reply_nterror(req, status);
3962 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3963 reply_unixerror(req, ERRHRD, ERRdiskfull);
3967 reply_outbuf(req, 1, 0);
3969 SSVAL(req->outbuf,smb_vwv0,nwritten);
3971 if (nwritten < (ssize_t)numtowrite) {
3972 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3973 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3976 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3979 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3981 END_PROFILE(SMBwrite);
3985 /****************************************************************************
3986 Ensure a buffer is a valid writeX for recvfile purposes.
3987 ****************************************************************************/
3989 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3990 (2*14) + /* word count (including bcc) */ \
3993 bool is_valid_writeX_buffer(const uint8_t *inbuf)
3996 connection_struct *conn = NULL;
3997 unsigned int doff = 0;
3998 size_t len = smb_len_large(inbuf);
4000 if (is_encrypted_packet(inbuf)) {
4001 /* Can't do this on encrypted
4006 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4010 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4011 CVAL(inbuf,smb_wct) != 14) {
4012 DEBUG(10,("is_valid_writeX_buffer: chained or "
4013 "invalid word length.\n"));
4017 conn = conn_find(SVAL(inbuf, smb_tid));
4019 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4023 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4026 if (IS_PRINT(conn)) {
4027 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4030 doff = SVAL(inbuf,smb_vwv11);
4032 numtowrite = SVAL(inbuf,smb_vwv10);
4034 if (len > doff && len - doff > 0xFFFF) {
4035 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4038 if (numtowrite == 0) {
4039 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4043 /* Ensure the sizes match up. */
4044 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4045 /* no pad byte...old smbclient :-( */
4046 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4048 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4052 if (len - doff != numtowrite) {
4053 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4054 "len = %u, doff = %u, numtowrite = %u\n",
4057 (unsigned int)numtowrite ));
4061 DEBUG(10,("is_valid_writeX_buffer: true "
4062 "len = %u, doff = %u, numtowrite = %u\n",
4065 (unsigned int)numtowrite ));
4070 /****************************************************************************
4071 Reply to a write and X.
4072 ****************************************************************************/
4074 void reply_write_and_X(struct smb_request *req)
4076 connection_struct *conn = req->conn;
4078 struct lock_struct lock;
4083 unsigned int smb_doff;
4084 unsigned int smblen;
4088 START_PROFILE(SMBwriteX);
4090 if ((req->wct != 12) && (req->wct != 14)) {
4091 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4092 END_PROFILE(SMBwriteX);
4096 numtowrite = SVAL(req->vwv+10, 0);
4097 smb_doff = SVAL(req->vwv+11, 0);
4098 smblen = smb_len(req->inbuf);
4100 if (req->unread_bytes > 0xFFFF ||
4101 (smblen > smb_doff &&
4102 smblen - smb_doff > 0xFFFF)) {
4103 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4106 if (req->unread_bytes) {
4107 /* Can't do a recvfile write on IPC$ */
4109 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4110 END_PROFILE(SMBwriteX);
4113 if (numtowrite != req->unread_bytes) {
4114 reply_doserror(req, ERRDOS, ERRbadmem);
4115 END_PROFILE(SMBwriteX);
4119 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4120 smb_doff + numtowrite > smblen) {
4121 reply_doserror(req, ERRDOS, ERRbadmem);
4122 END_PROFILE(SMBwriteX);
4127 /* If it's an IPC, pass off the pipe handler. */
4129 if (req->unread_bytes) {
4130 reply_doserror(req, ERRDOS, ERRbadmem);
4131 END_PROFILE(SMBwriteX);
4134 reply_pipe_write_and_X(req);
4135 END_PROFILE(SMBwriteX);
4139 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4140 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4141 write_through = BITSETW(req->vwv+7,0);
4143 if (!check_fsp(conn, req, fsp)) {
4144 END_PROFILE(SMBwriteX);
4148 if (!CHECK_WRITE(fsp)) {
4149 reply_doserror(req, ERRDOS, ERRbadaccess);
4150 END_PROFILE(SMBwriteX);
4154 data = smb_base(req->inbuf) + smb_doff;
4156 if(req->wct == 14) {
4157 #ifdef LARGE_SMB_OFF_T
4159 * This is a large offset (64 bit) write.
4161 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4163 #else /* !LARGE_SMB_OFF_T */
4166 * Ensure we haven't been sent a >32 bit offset.
4169 if(IVAL(req->vwv+12, 0) != 0) {
4170 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4171 "used and we don't support 64 bit offsets.\n",
4172 (unsigned int)IVAL(req->vwv+12, 0) ));
4173 reply_doserror(req, ERRDOS, ERRbadaccess);
4174 END_PROFILE(SMBwriteX);
4178 #endif /* LARGE_SMB_OFF_T */
4181 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4182 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4185 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4186 reply_doserror(req, ERRDOS, ERRlock);
4187 END_PROFILE(SMBwriteX);
4191 /* X/Open SMB protocol says that, unlike SMBwrite
4192 if the length is zero then NO truncation is
4193 done, just a write of zero. To truncate a file,
4196 if(numtowrite == 0) {
4200 if ((req->unread_bytes == 0) &&
4201 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4206 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4209 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4210 reply_unixerror(req, ERRHRD, ERRdiskfull);
4214 reply_outbuf(req, 6, 0);
4215 SSVAL(req->outbuf,smb_vwv2,nwritten);
4216 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4218 if (nwritten < (ssize_t)numtowrite) {
4219 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4220 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4223 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4224 fsp->fnum, (int)numtowrite, (int)nwritten));
4226 status = sync_file(conn, fsp, write_through);
4227 if (!NT_STATUS_IS_OK(status)) {
4228 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4229 fsp->fsp_name, nt_errstr(status) ));
4230 reply_nterror(req, status);
4234 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4236 END_PROFILE(SMBwriteX);
4241 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4243 END_PROFILE(SMBwriteX);
4247 /****************************************************************************
4249 ****************************************************************************/
4251 void reply_lseek(struct smb_request *req)
4253 connection_struct *conn = req->conn;
4259 START_PROFILE(SMBlseek);
4262 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4263 END_PROFILE(SMBlseek);
4267 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4269 if (!check_fsp(conn, req, fsp)) {
4273 flush_write_cache(fsp, SEEK_FLUSH);
4275 mode = SVAL(req->vwv+1, 0) & 3;
4276 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4277 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4286 res = fsp->fh->pos + startpos;
4297 if (umode == SEEK_END) {
4298 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4299 if(errno == EINVAL) {
4300 SMB_OFF_T current_pos = startpos;
4301 SMB_STRUCT_STAT sbuf;
4303 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4304 reply_unixerror(req, ERRDOS,
4306 END_PROFILE(SMBlseek);
4310 current_pos += sbuf.st_size;
4312 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4317 reply_unixerror(req, ERRDOS, ERRnoaccess);
4318 END_PROFILE(SMBlseek);
4325 reply_outbuf(req, 2, 0);
4326 SIVAL(req->outbuf,smb_vwv0,res);
4328 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4329 fsp->fnum, (double)startpos, (double)res, mode));
4331 END_PROFILE(SMBlseek);
4335 /****************************************************************************
4337 ****************************************************************************/
4339 void reply_flush(struct smb_request *req)
4341 connection_struct *conn = req->conn;
4345 START_PROFILE(SMBflush);
4348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4352 fnum = SVAL(req->vwv+0, 0);
4353 fsp = file_fsp(req, fnum);
4355 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4360 file_sync_all(conn);
4362 NTSTATUS status = sync_file(conn, fsp, True);
4363 if (!NT_STATUS_IS_OK(status)) {
4364 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4365 fsp->fsp_name, nt_errstr(status) ));
4366 reply_nterror(req, status);
4367 END_PROFILE(SMBflush);
4372 reply_outbuf(req, 0, 0);
4374 DEBUG(3,("flush\n"));
4375 END_PROFILE(SMBflush);
4379 /****************************************************************************
4381 conn POINTER CAN BE NULL HERE !
4382 ****************************************************************************/
4384 void reply_exit(struct smb_request *req)
4386 START_PROFILE(SMBexit);
4388 file_close_pid(req->smbpid, req->vuid);
4390 reply_outbuf(req, 0, 0);
4392 DEBUG(3,("exit\n"));
4394 END_PROFILE(SMBexit);
4398 /****************************************************************************
4399 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4400 ****************************************************************************/
4402 void reply_close(struct smb_request *req)
4404 connection_struct *conn = req->conn;
4405 NTSTATUS status = NT_STATUS_OK;
4406 files_struct *fsp = NULL;
4407 START_PROFILE(SMBclose);
4410 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4411 END_PROFILE(SMBclose);
4415 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4418 * We can only use check_fsp if we know it's not a directory.
4421 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4422 reply_doserror(req, ERRDOS, ERRbadfid);
4423 END_PROFILE(SMBclose);
4427 if(fsp->is_directory) {
4429 * Special case - close NT SMB directory handle.
4431 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4432 status = close_file(req, fsp, NORMAL_CLOSE);
4436 * Close ordinary file.
4439 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4440 fsp->fh->fd, fsp->fnum,
4441 conn->num_files_open));
4444 * Take care of any time sent in the close.
4447 t = srv_make_unix_date3(req->vwv+1);
4448 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4451 * close_file() returns the unix errno if an error
4452 * was detected on close - normally this is due to
4453 * a disk full error. If not then it was probably an I/O error.
4456 status = close_file(req, fsp, NORMAL_CLOSE);
4459 if (!NT_STATUS_IS_OK(status)) {
4460 reply_nterror(req, status);
4461 END_PROFILE(SMBclose);
4465 reply_outbuf(req, 0, 0);
4466 END_PROFILE(SMBclose);
4470 /****************************************************************************
4471 Reply to a writeclose (Core+ protocol).
4472 ****************************************************************************/
4474 void reply_writeclose(struct smb_request *req)
4476 connection_struct *conn = req->conn;
4478 ssize_t nwritten = -1;
4479 NTSTATUS close_status = NT_STATUS_OK;
4482 struct timespec mtime;
4484 struct lock_struct lock;
4486 START_PROFILE(SMBwriteclose);
4489 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4490 END_PROFILE(SMBwriteclose);
4494 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4496 if (!check_fsp(conn, req, fsp)) {
4497 END_PROFILE(SMBwriteclose);
4500 if (!CHECK_WRITE(fsp)) {
4501 reply_doserror(req, ERRDOS,ERRbadaccess);
4502 END_PROFILE(SMBwriteclose);
4506 numtowrite = SVAL(req->vwv+1, 0);
4507 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4508 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4509 data = (const char *)req->buf + 1;
4512 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4513 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4516 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4517 reply_doserror(req, ERRDOS,ERRlock);
4518 END_PROFILE(SMBwriteclose);
4523 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4525 set_close_write_time(fsp, mtime);
4528 * More insanity. W2K only closes the file if writelen > 0.
4533 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4535 close_status = close_file(req, fsp, NORMAL_CLOSE);
4538 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4539 fsp->fnum, (int)numtowrite, (int)nwritten,
4540 conn->num_files_open));
4542 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4543 reply_doserror(req, ERRHRD, ERRdiskfull);
4547 if(!NT_STATUS_IS_OK(close_status)) {
4548 reply_nterror(req, close_status);
4552 reply_outbuf(req, 1, 0);
4554 SSVAL(req->outbuf,smb_vwv0,nwritten);
4558 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4561 END_PROFILE(SMBwriteclose);
4566 #define DBGC_CLASS DBGC_LOCKING
4568 /****************************************************************************
4570 ****************************************************************************/
4572 void reply_lock(struct smb_request *req)
4574 connection_struct *conn = req->conn;
4575 uint64_t count,offset;
4578 struct byte_range_lock *br_lck = NULL;
4580 START_PROFILE(SMBlock);
4583 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4584 END_PROFILE(SMBlock);
4588 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4590 if (!check_fsp(conn, req, fsp)) {
4591 END_PROFILE(SMBlock);
4595 count = (uint64_t)IVAL(req->vwv+1, 0);
4596 offset = (uint64_t)IVAL(req->vwv+3, 0);
4598 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4599 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4601 br_lck = do_lock(smbd_messaging_context(),
4608 False, /* Non-blocking lock. */
4613 TALLOC_FREE(br_lck);
4615 if (NT_STATUS_V(status)) {
4616 reply_nterror(req, status);
4617 END_PROFILE(SMBlock);
4621 reply_outbuf(req, 0, 0);
4623 END_PROFILE(SMBlock);
4627 /****************************************************************************
4629 ****************************************************************************/
4631 void reply_unlock(struct smb_request *req)
4633 connection_struct *conn = req->conn;
4634 uint64_t count,offset;
4638 START_PROFILE(SMBunlock);
4641 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4642 END_PROFILE(SMBunlock);
4646 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4648 if (!check_fsp(conn, req, fsp)) {
4649 END_PROFILE(SMBunlock);
4653 count = (uint64_t)IVAL(req->vwv+1, 0);
4654 offset = (uint64_t)IVAL(req->vwv+3, 0);
4656 status = do_unlock(smbd_messaging_context(),
4663 if (NT_STATUS_V(status)) {
4664 reply_nterror(req, status);
4665 END_PROFILE(SMBunlock);
4669 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4670 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4672 reply_outbuf(req, 0, 0);
4674 END_PROFILE(SMBunlock);
4679 #define DBGC_CLASS DBGC_ALL
4681 /****************************************************************************
4683 conn POINTER CAN BE NULL HERE !
4684 ****************************************************************************/
4686 void reply_tdis(struct smb_request *req)
4688 connection_struct *conn = req->conn;
4689 START_PROFILE(SMBtdis);
4692 DEBUG(4,("Invalid connection in tdis\n"));
4693 reply_doserror(req, ERRSRV, ERRinvnid);
4694 END_PROFILE(SMBtdis);
4700 close_cnum(conn,req->vuid);
4703 reply_outbuf(req, 0, 0);
4704 END_PROFILE(SMBtdis);
4708 /****************************************************************************
4710 conn POINTER CAN BE NULL HERE !
4711 ****************************************************************************/
4713 void reply_echo(struct smb_request *req)
4715 connection_struct *conn = req->conn;
4716 struct smb_perfcount_data local_pcd;
4717 struct smb_perfcount_data *cur_pcd;
4721 START_PROFILE(SMBecho);
4723 smb_init_perfcount_data(&local_pcd);
4726 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4727 END_PROFILE(SMBecho);
4731 smb_reverb = SVAL(req->vwv+0, 0);
4733 reply_outbuf(req, 1, req->buflen);
4735 /* copy any incoming data back out */
4736 if (req->buflen > 0) {
4737 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4740 if (smb_reverb > 100) {
4741 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4745 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4747 /* this makes sure we catch the request pcd */
4748 if (seq_num == smb_reverb) {
4749 cur_pcd = &req->pcd;
4751 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4752 cur_pcd = &local_pcd;
4755 SSVAL(req->outbuf,smb_vwv0,seq_num);
4757 show_msg((char *)req->outbuf);
4758 if (!srv_send_smb(smbd_server_fd(),
4759 (char *)req->outbuf,
4760 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4762 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4765 DEBUG(3,("echo %d times\n", smb_reverb));
4767 TALLOC_FREE(req->outbuf);
4769 END_PROFILE(SMBecho);
4773 /****************************************************************************
4774 Reply to a printopen.
4775 ****************************************************************************/
4777 void reply_printopen(struct smb_request *req)
4779 connection_struct *conn = req->conn;
4781 SMB_STRUCT_STAT sbuf;
4784 START_PROFILE(SMBsplopen);
4787 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4788 END_PROFILE(SMBsplopen);
4792 if (!CAN_PRINT(conn)) {
4793 reply_doserror(req, ERRDOS, ERRnoaccess);
4794 END_PROFILE(SMBsplopen);
4798 status = file_new(req, conn, &fsp);
4799 if(!NT_STATUS_IS_OK(status)) {
4800 reply_nterror(req, status);
4801 END_PROFILE(SMBsplopen);
4805 /* Open for exclusive use, write only. */
4806 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4808 if (!NT_STATUS_IS_OK(status)) {
4809 reply_nterror(req, status);
4810 END_PROFILE(SMBsplopen);
4814 reply_outbuf(req, 1, 0);
4815 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4817 DEBUG(3,("openprint fd=%d fnum=%d\n",
4818 fsp->fh->fd, fsp->fnum));
4820 END_PROFILE(SMBsplopen);
4824 /****************************************************************************
4825 Reply to a printclose.
4826 ****************************************************************************/
4828 void reply_printclose(struct smb_request *req)
4830 connection_struct *conn = req->conn;
4834 START_PROFILE(SMBsplclose);
4837 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4838 END_PROFILE(SMBsplclose);
4842 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4844 if (!check_fsp(conn, req, fsp)) {
4845 END_PROFILE(SMBsplclose);
4849 if (!CAN_PRINT(conn)) {
4850 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4851 END_PROFILE(SMBsplclose);
4855 DEBUG(3,("printclose fd=%d fnum=%d\n",
4856 fsp->fh->fd,fsp->fnum));
4858 status = close_file(req, fsp, NORMAL_CLOSE);
4860 if(!NT_STATUS_IS_OK(status)) {
4861 reply_nterror(req, status);
4862 END_PROFILE(SMBsplclose);
4866 reply_outbuf(req, 0, 0);
4868 END_PROFILE(SMBsplclose);
4872 /****************************************************************************
4873 Reply to a printqueue.
4874 ****************************************************************************/
4876 void reply_printqueue(struct smb_request *req)
4878 connection_struct *conn = req->conn;
4882 START_PROFILE(SMBsplretq);
4885 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4886 END_PROFILE(SMBsplretq);
4890 max_count = SVAL(req->vwv+0, 0);
4891 start_index = SVAL(req->vwv+1, 0);
4893 /* we used to allow the client to get the cnum wrong, but that
4894 is really quite gross and only worked when there was only
4895 one printer - I think we should now only accept it if they
4896 get it right (tridge) */
4897 if (!CAN_PRINT(conn)) {
4898 reply_doserror(req, ERRDOS, ERRnoaccess);
4899 END_PROFILE(SMBsplretq);
4903 reply_outbuf(req, 2, 3);
4904 SSVAL(req->outbuf,smb_vwv0,0);
4905 SSVAL(req->outbuf,smb_vwv1,0);
4906 SCVAL(smb_buf(req->outbuf),0,1);
4907 SSVAL(smb_buf(req->outbuf),1,0);
4909 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4910 start_index, max_count));
4913 print_queue_struct *queue = NULL;
4914 print_status_struct status;
4915 int count = print_queue_status(SNUM(conn), &queue, &status);
4916 int num_to_get = ABS(max_count);
4917 int first = (max_count>0?start_index:start_index+max_count+1);
4923 num_to_get = MIN(num_to_get,count-first);
4926 for (i=first;i<first+num_to_get;i++) {
4930 srv_put_dos_date2(p,0,queue[i].time);
4931 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4932 SSVAL(p,5, queue[i].job);
4933 SIVAL(p,7,queue[i].size);
4935 srvstr_push(blob, req->flags2, p+12,
4936 queue[i].fs_user, 16, STR_ASCII);
4938 if (message_push_blob(
4941 blob, sizeof(blob))) == -1) {
4942 reply_nterror(req, NT_STATUS_NO_MEMORY);
4943 END_PROFILE(SMBsplretq);
4949 SSVAL(req->outbuf,smb_vwv0,count);
4950 SSVAL(req->outbuf,smb_vwv1,
4951 (max_count>0?first+count:first-1));
4952 SCVAL(smb_buf(req->outbuf),0,1);
4953 SSVAL(smb_buf(req->outbuf),1,28*count);
4958 DEBUG(3,("%d entries returned in queue\n",count));
4961 END_PROFILE(SMBsplretq);
4965 /****************************************************************************
4966 Reply to a printwrite.
4967 ****************************************************************************/
4969 void reply_printwrite(struct smb_request *req)
4971 connection_struct *conn = req->conn;
4976 START_PROFILE(SMBsplwr);
4979 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4980 END_PROFILE(SMBsplwr);
4984 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4986 if (!check_fsp(conn, req, fsp)) {
4987 END_PROFILE(SMBsplwr);
4991 if (!CAN_PRINT(conn)) {
4992 reply_doserror(req, ERRDOS, ERRnoaccess);
4993 END_PROFILE(SMBsplwr);
4997 if (!CHECK_WRITE(fsp)) {
4998 reply_doserror(req, ERRDOS, ERRbadaccess);
4999 END_PROFILE(SMBsplwr);
5003 numtowrite = SVAL(req->buf, 1);
5005 if (req->buflen < numtowrite + 3) {
5006 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5007 END_PROFILE(SMBsplwr);
5011 data = (const char *)req->buf + 3;
5013 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5014 reply_unixerror(req, ERRHRD, ERRdiskfull);
5015 END_PROFILE(SMBsplwr);
5019 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5021 END_PROFILE(SMBsplwr);
5025 /****************************************************************************
5027 ****************************************************************************/
5029 void reply_mkdir(struct smb_request *req)
5031 connection_struct *conn = req->conn;
5032 char *directory = NULL;
5034 SMB_STRUCT_STAT sbuf;
5035 TALLOC_CTX *ctx = talloc_tos();
5037 START_PROFILE(SMBmkdir);
5039 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5040 STR_TERMINATE, &status);
5041 if (!NT_STATUS_IS_OK(status)) {
5042 reply_nterror(req, status);
5043 END_PROFILE(SMBmkdir);
5047 status = resolve_dfspath(ctx, conn,
5048 req->flags2 & FLAGS2_DFS_PATHNAMES,
5051 if (!NT_STATUS_IS_OK(status)) {
5052 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5053 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5054 ERRSRV, ERRbadpath);
5055 END_PROFILE(SMBmkdir);
5058 reply_nterror(req, status);
5059 END_PROFILE(SMBmkdir);
5063 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
5064 if (!NT_STATUS_IS_OK(status)) {
5065 reply_nterror(req, status);
5066 END_PROFILE(SMBmkdir);
5070 status = check_name(conn, directory);
5071 if (!NT_STATUS_IS_OK(status)) {
5072 reply_nterror(req, status);
5073 END_PROFILE(SMBmkdir);
5077 status = create_directory(conn, req, directory);
5079 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5081 if (!NT_STATUS_IS_OK(status)) {
5083 if (!use_nt_status()
5084 && NT_STATUS_EQUAL(status,
5085 NT_STATUS_OBJECT_NAME_COLLISION)) {
5087 * Yes, in the DOS error code case we get a
5088 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5089 * samba4 torture test.
5091 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5094 reply_nterror(req, status);
5095 END_PROFILE(SMBmkdir);
5099 reply_outbuf(req, 0, 0);
5101 DEBUG( 3, ( "mkdir %s\n", directory ) );
5103 END_PROFILE(SMBmkdir);
5107 /****************************************************************************
5108 Static function used by reply_rmdir to delete an entire directory
5109 tree recursively. Return True on ok, False on fail.
5110 ****************************************************************************/
5112 static bool recursive_rmdir(TALLOC_CTX *ctx,
5113 connection_struct *conn,
5116 const char *dname = NULL;
5120 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5126 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5127 char *fullname = NULL;
5129 if (ISDOT(dname) || ISDOTDOT(dname)) {
5133 if (!is_visible_file(conn, directory, dname, &st, False)) {
5137 /* Construct the full name. */
5138 fullname = talloc_asprintf(ctx,
5148 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5153 if(st.st_mode & S_IFDIR) {
5154 if(!recursive_rmdir(ctx, conn, fullname)) {
5158 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5162 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5166 TALLOC_FREE(fullname);
5168 TALLOC_FREE(dir_hnd);
5172 /****************************************************************************
5173 The internals of the rmdir code - called elsewhere.
5174 ****************************************************************************/
5176 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5177 connection_struct *conn,
5178 const char *directory)
5183 /* Might be a symlink. */
5184 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5185 return map_nt_error_from_unix(errno);
5188 if (S_ISLNK(st.st_mode)) {
5189 /* Is what it points to a directory ? */
5190 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5191 return map_nt_error_from_unix(errno);
5193 if (!(S_ISDIR(st.st_mode))) {
5194 return NT_STATUS_NOT_A_DIRECTORY;
5196 ret = SMB_VFS_UNLINK(conn,directory);
5198 ret = SMB_VFS_RMDIR(conn,directory);
5201 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5202 FILE_NOTIFY_CHANGE_DIR_NAME,
5204 return NT_STATUS_OK;
5207 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5209 * Check to see if the only thing in this directory are
5210 * vetoed files/directories. If so then delete them and
5211 * retry. If we fail to delete any of them (and we *don't*
5212 * do a recursive delete) then fail the rmdir.
5216 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5217 directory, NULL, 0);
5219 if(dir_hnd == NULL) {
5224 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5225 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5227 if (!is_visible_file(conn, directory, dname, &st, False))
5229 if(!IS_VETO_PATH(conn, dname)) {
5230 TALLOC_FREE(dir_hnd);
5236 /* We only have veto files/directories.
5237 * Are we allowed to delete them ? */
5239 if(!lp_recursive_veto_delete(SNUM(conn))) {
5240 TALLOC_FREE(dir_hnd);
5245 /* Do a recursive delete. */
5246 RewindDir(dir_hnd,&dirpos);
5247 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5248 char *fullname = NULL;
5250 if (ISDOT(dname) || ISDOTDOT(dname)) {
5253 if (!is_visible_file(conn, directory, dname, &st, False)) {
5257 fullname = talloc_asprintf(ctx,
5267 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5270 if(st.st_mode & S_IFDIR) {
5271 if(!recursive_rmdir(ctx, conn, fullname)) {
5274 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5277 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5280 TALLOC_FREE(fullname);
5282 TALLOC_FREE(dir_hnd);
5283 /* Retry the rmdir */
5284 ret = SMB_VFS_RMDIR(conn,directory);
5290 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5291 "%s\n", directory,strerror(errno)));
5292 return map_nt_error_from_unix(errno);
5295 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5296 FILE_NOTIFY_CHANGE_DIR_NAME,
5299 return NT_STATUS_OK;
5302 /****************************************************************************
5304 ****************************************************************************/
5306 void reply_rmdir(struct smb_request *req)
5308 connection_struct *conn = req->conn;
5309 char *directory = NULL;
5310 SMB_STRUCT_STAT sbuf;
5312 TALLOC_CTX *ctx = talloc_tos();
5314 START_PROFILE(SMBrmdir);
5316 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5317 STR_TERMINATE, &status);
5318 if (!NT_STATUS_IS_OK(status)) {
5319 reply_nterror(req, status);
5320 END_PROFILE(SMBrmdir);
5324 status = resolve_dfspath(ctx, conn,
5325 req->flags2 & FLAGS2_DFS_PATHNAMES,
5328 if (!NT_STATUS_IS_OK(status)) {
5329 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5330 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5331 ERRSRV, ERRbadpath);
5332 END_PROFILE(SMBrmdir);
5335 reply_nterror(req, status);
5336 END_PROFILE(SMBrmdir);
5340 status = unix_convert(ctx, conn, directory, False, &directory,
5342 if (!NT_STATUS_IS_OK(status)) {
5343 reply_nterror(req, status);
5344 END_PROFILE(SMBrmdir);
5348 status = check_name(conn, directory);
5349 if (!NT_STATUS_IS_OK(status)) {
5350 reply_nterror(req, status);
5351 END_PROFILE(SMBrmdir);
5355 dptr_closepath(directory, req->smbpid);
5356 status = rmdir_internals(ctx, conn, directory);
5357 if (!NT_STATUS_IS_OK(status)) {
5358 reply_nterror(req, status);
5359 END_PROFILE(SMBrmdir);
5363 reply_outbuf(req, 0, 0);
5365 DEBUG( 3, ( "rmdir %s\n", directory ) );
5367 END_PROFILE(SMBrmdir);
5371 /*******************************************************************
5372 Resolve wildcards in a filename rename.
5373 ********************************************************************/
5375 static bool resolve_wildcards(TALLOC_CTX *ctx,
5380 char *name2_copy = NULL;
5385 char *p,*p2, *pname1, *pname2;
5387 name2_copy = talloc_strdup(ctx, name2);
5392 pname1 = strrchr_m(name1,'/');
5393 pname2 = strrchr_m(name2_copy,'/');
5395 if (!pname1 || !pname2) {
5399 /* Truncate the copy of name2 at the last '/' */
5402 /* Now go past the '/' */
5406 root1 = talloc_strdup(ctx, pname1);
5407 root2 = talloc_strdup(ctx, pname2);
5409 if (!root1 || !root2) {
5413 p = strrchr_m(root1,'.');
5416 ext1 = talloc_strdup(ctx, p+1);
5418 ext1 = talloc_strdup(ctx, "");
5420 p = strrchr_m(root2,'.');
5423 ext2 = talloc_strdup(ctx, p+1);
5425 ext2 = talloc_strdup(ctx, "");
5428 if (!ext1 || !ext2) {
5436 /* Hmmm. Should this be mb-aware ? */
5439 } else if (*p2 == '*') {
5441 root2 = talloc_asprintf(ctx, "%s%s",
5460 /* Hmmm. Should this be mb-aware ? */
5463 } else if (*p2 == '*') {
5465 ext2 = talloc_asprintf(ctx, "%s%s",
5481 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5486 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5498 /****************************************************************************
5499 Ensure open files have their names updated. Updated to notify other smbd's
5501 ****************************************************************************/
5503 static void rename_open_files(connection_struct *conn,
5504 struct share_mode_lock *lck,
5505 const char *newname)
5508 bool did_rename = False;
5510 for(fsp = file_find_di_first(lck->id); fsp;
5511 fsp = file_find_di_next(fsp)) {
5512 /* fsp_name is a relative path under the fsp. To change this for other
5513 sharepaths we need to manipulate relative paths. */
5514 /* TODO - create the absolute path and manipulate the newname
5515 relative to the sharepath. */
5516 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5519 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5520 fsp->fnum, file_id_string_tos(&fsp->file_id),
5521 fsp->fsp_name, newname ));
5522 string_set(&fsp->fsp_name, newname);
5527 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5528 file_id_string_tos(&lck->id), newname ));
5531 /* Send messages to all smbd's (not ourself) that the name has changed. */
5532 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5536 /****************************************************************************
5537 We need to check if the source path is a parent directory of the destination
5538 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5539 refuse the rename with a sharing violation. Under UNIX the above call can
5540 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5541 probably need to check that the client is a Windows one before disallowing
5542 this as a UNIX client (one with UNIX extensions) can know the source is a
5543 symlink and make this decision intelligently. Found by an excellent bug
5544 report from <AndyLiebman@aol.com>.
5545 ****************************************************************************/
5547 static bool rename_path_prefix_equal(const char *src, const char *dest)
5549 const char *psrc = src;
5550 const char *pdst = dest;
5553 if (psrc[0] == '.' && psrc[1] == '/') {
5556 if (pdst[0] == '.' && pdst[1] == '/') {
5559 if ((slen = strlen(psrc)) > strlen(pdst)) {
5562 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5566 * Do the notify calls from a rename
5569 static void notify_rename(connection_struct *conn, bool is_dir,
5570 const char *oldpath, const char *newpath)
5572 char *olddir, *newdir;
5573 const char *oldname, *newname;
5576 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5577 : FILE_NOTIFY_CHANGE_FILE_NAME;
5579 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5580 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5581 TALLOC_FREE(olddir);
5585 if (strcmp(olddir, newdir) == 0) {
5586 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5587 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5590 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5591 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5593 TALLOC_FREE(olddir);
5594 TALLOC_FREE(newdir);
5596 /* this is a strange one. w2k3 gives an additional event for
5597 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5598 files, but not directories */
5600 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5601 FILE_NOTIFY_CHANGE_ATTRIBUTES
5602 |FILE_NOTIFY_CHANGE_CREATION,
5607 /****************************************************************************
5608 Rename an open file - given an fsp.
5609 ****************************************************************************/
5611 NTSTATUS rename_internals_fsp(connection_struct *conn,
5614 const char *newname_last_component,
5616 bool replace_if_exists)
5618 TALLOC_CTX *ctx = talloc_tos();
5619 SMB_STRUCT_STAT sbuf, sbuf1;
5620 NTSTATUS status = NT_STATUS_OK;
5621 struct share_mode_lock *lck = NULL;
5622 bool dst_exists, old_is_stream, new_is_stream;
5626 status = check_name(conn, newname);
5627 if (!NT_STATUS_IS_OK(status)) {
5631 /* Ensure newname contains a '/' */
5632 if(strrchr_m(newname,'/') == 0) {
5633 newname = talloc_asprintf(ctx,
5637 return NT_STATUS_NO_MEMORY;
5642 * Check for special case with case preserving and not
5643 * case sensitive. If the old last component differs from the original
5644 * last component only by case, then we should allow
5645 * the rename (user is trying to change the case of the
5649 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5650 strequal(newname, fsp->fsp_name)) {
5652 char *newname_modified_last_component = NULL;
5655 * Get the last component of the modified name.
5656 * Note that we guarantee that newname contains a '/'
5659 p = strrchr_m(newname,'/');
5660 newname_modified_last_component = talloc_strdup(ctx,
5662 if (!newname_modified_last_component) {
5663 return NT_STATUS_NO_MEMORY;
5666 if(strcsequal(newname_modified_last_component,
5667 newname_last_component) == False) {
5669 * Replace the modified last component with
5672 *p = '\0'; /* Truncate at the '/' */
5673 newname = talloc_asprintf(ctx,
5676 newname_last_component);
5681 * If the src and dest names are identical - including case,
5682 * don't do the rename, just return success.
5685 if (strcsequal(fsp->fsp_name, newname)) {
5686 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5688 return NT_STATUS_OK;
5691 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5692 new_is_stream = is_ntfs_stream_name(newname);
5694 /* Return the correct error code if both names aren't streams. */
5695 if (!old_is_stream && new_is_stream) {
5696 return NT_STATUS_OBJECT_NAME_INVALID;
5699 if (old_is_stream && !new_is_stream) {
5700 return NT_STATUS_INVALID_PARAMETER;
5704 * Have vfs_object_exist also fill sbuf1
5706 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5708 if(!replace_if_exists && dst_exists) {
5709 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5710 fsp->fsp_name,newname));
5711 return NT_STATUS_OBJECT_NAME_COLLISION;
5715 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5716 files_struct *dst_fsp = file_find_di_first(fileid);
5717 /* The file can be open when renaming a stream */
5718 if (dst_fsp && !new_is_stream) {
5719 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5720 return NT_STATUS_ACCESS_DENIED;
5724 /* Ensure we have a valid stat struct for the source. */
5725 if (fsp->fh->fd != -1) {
5726 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5727 return map_nt_error_from_unix(errno);
5731 if (fsp->posix_open) {
5732 ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
5734 ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
5737 return map_nt_error_from_unix(errno);
5741 status = can_rename(conn, fsp, attrs, &sbuf);
5743 if (!NT_STATUS_IS_OK(status)) {
5744 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5745 nt_errstr(status), fsp->fsp_name,newname));
5746 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5747 status = NT_STATUS_ACCESS_DENIED;
5751 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5752 return NT_STATUS_ACCESS_DENIED;
5755 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5759 * We have the file open ourselves, so not being able to get the
5760 * corresponding share mode lock is a fatal error.
5763 SMB_ASSERT(lck != NULL);
5765 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5766 uint32 create_options = fsp->fh->private_options;
5768 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5769 fsp->fsp_name,newname));
5771 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5773 rename_open_files(conn, lck, newname);
5776 * A rename acts as a new file create w.r.t. allowing an initial delete
5777 * on close, probably because in Windows there is a new handle to the
5778 * new file. If initial delete on close was requested but not
5779 * originally set, we need to set it here. This is probably not 100% correct,
5780 * but will work for the CIFSFS client which in non-posix mode
5781 * depends on these semantics. JRA.
5784 if (create_options & FILE_DELETE_ON_CLOSE) {
5785 status = can_set_delete_on_close(fsp, True, 0);
5787 if (NT_STATUS_IS_OK(status)) {
5788 /* Note that here we set the *inital* delete on close flag,
5789 * not the regular one. The magic gets handled in close. */
5790 fsp->initial_delete_on_close = True;
5794 return NT_STATUS_OK;
5799 if (errno == ENOTDIR || errno == EISDIR) {
5800 status = NT_STATUS_OBJECT_NAME_COLLISION;
5802 status = map_nt_error_from_unix(errno);
5805 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5806 nt_errstr(status), fsp->fsp_name,newname));
5811 /****************************************************************************
5812 The guts of the rename command, split out so it may be called by the NT SMB
5814 ****************************************************************************/
5816 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5817 connection_struct *conn,
5818 struct smb_request *req,
5819 const char *name_in,
5820 const char *newname_in,
5822 bool replace_if_exists,
5825 uint32_t access_mask)
5827 char *directory = NULL;
5829 char *last_component_src = NULL;
5830 char *last_component_dest = NULL;
5832 char *newname = NULL;
5835 NTSTATUS status = NT_STATUS_OK;
5836 SMB_STRUCT_STAT sbuf1, sbuf2;
5837 struct smb_Dir *dir_hnd = NULL;
5840 int create_options = 0;
5841 bool posix_pathnames = lp_posix_pathnames();
5846 status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5847 &last_component_src, &sbuf1);
5848 if (!NT_STATUS_IS_OK(status)) {
5852 status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5853 &last_component_dest, &sbuf2);
5854 if (!NT_STATUS_IS_OK(status)) {
5859 * Split the old name into directory and last component
5860 * strings. Note that unix_convert may have stripped off a
5861 * leading ./ from both name and newname if the rename is
5862 * at the root of the share. We need to make sure either both
5863 * name and newname contain a / character or neither of them do
5864 * as this is checked in resolve_wildcards().
5867 p = strrchr_m(name,'/');
5869 directory = talloc_strdup(ctx, ".");
5871 return NT_STATUS_NO_MEMORY;
5876 directory = talloc_strdup(ctx, name);
5878 return NT_STATUS_NO_MEMORY;
5881 *p = '/'; /* Replace needed for exceptional test below. */
5885 * We should only check the mangled cache
5886 * here if unix_convert failed. This means
5887 * that the path in 'mask' doesn't exist
5888 * on the file system and so we need to look
5889 * for a possible mangle. This patch from
5890 * Tine Smukavec <valentin.smukavec@hermes.si>.
5893 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5894 char *new_mask = NULL;
5895 mangle_lookup_name_from_8_3(ctx,
5904 if (!src_has_wild) {
5908 * No wildcards - just process the one file.
5910 bool is_short_name = mangle_is_8_3(name, True, conn->params);
5912 /* Add a terminating '/' to the directory name. */
5913 directory = talloc_asprintf_append(directory,
5917 return NT_STATUS_NO_MEMORY;
5920 /* Ensure newname contains a '/' also */
5921 if(strrchr_m(newname,'/') == 0) {
5922 newname = talloc_asprintf(ctx,
5926 return NT_STATUS_NO_MEMORY;
5930 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5931 "case_preserve = %d, short case preserve = %d, "
5932 "directory = %s, newname = %s, "
5933 "last_component_dest = %s, is_8_3 = %d\n",
5934 conn->case_sensitive, conn->case_preserve,
5935 conn->short_case_preserve, directory,
5936 newname, last_component_dest, is_short_name));
5938 /* The dest name still may have wildcards. */
5939 if (dest_has_wild) {
5940 char *mod_newname = NULL;
5941 if (!resolve_wildcards(ctx,
5942 directory,newname,&mod_newname)) {
5943 DEBUG(6, ("rename_internals: resolve_wildcards "
5947 return NT_STATUS_NO_MEMORY;
5949 newname = mod_newname;
5953 if (posix_pathnames) {
5954 SMB_VFS_LSTAT(conn, directory, &sbuf1);
5956 SMB_VFS_STAT(conn, directory, &sbuf1);
5959 if (S_ISDIR(sbuf1.st_mode)) {
5960 create_options |= FILE_DIRECTORY_FILE;
5963 status = SMB_VFS_CREATE_FILE(
5966 0, /* root_dir_fid */
5967 directory, /* fname */
5968 0, /* create_file_flags */
5969 access_mask, /* access_mask */
5970 (FILE_SHARE_READ | /* share_access */
5972 FILE_OPEN, /* create_disposition*/
5973 create_options, /* create_options */
5974 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
5975 0, /* oplock_request */
5976 0, /* allocation_size */
5981 &sbuf1); /* psbuf */
5983 if (!NT_STATUS_IS_OK(status)) {
5984 DEBUG(3, ("Could not open rename source %s: %s\n",
5985 directory, nt_errstr(status)));
5989 status = rename_internals_fsp(conn, fsp, newname,
5990 last_component_dest,
5991 attrs, replace_if_exists);
5993 close_file(req, fsp, NORMAL_CLOSE);
5995 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5996 nt_errstr(status), directory,newname));
6002 * Wildcards - process each file that matches.
6004 if (strequal(mask,"????????.???")) {
6009 status = check_name(conn, directory);
6010 if (!NT_STATUS_IS_OK(status)) {
6014 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
6015 if (dir_hnd == NULL) {
6016 return map_nt_error_from_unix(errno);
6019 status = NT_STATUS_NO_SUCH_FILE;
6021 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6022 * - gentest fix. JRA
6025 while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
6026 files_struct *fsp = NULL;
6028 char *destname = NULL;
6029 bool sysdir_entry = False;
6031 /* Quick check for "." and ".." */
6032 if (ISDOT(dname) || ISDOTDOT(dname)) {
6034 sysdir_entry = True;
6040 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6044 if(!mask_match(dname, mask, conn->case_sensitive)) {
6049 status = NT_STATUS_OBJECT_NAME_INVALID;
6053 fname = talloc_asprintf(ctx,
6058 return NT_STATUS_NO_MEMORY;
6061 if (!resolve_wildcards(ctx,
6062 fname,newname,&destname)) {
6063 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6069 return NT_STATUS_NO_MEMORY;
6073 if (posix_pathnames) {
6074 SMB_VFS_LSTAT(conn, fname, &sbuf1);
6076 SMB_VFS_STAT(conn, fname, &sbuf1);
6081 if (S_ISDIR(sbuf1.st_mode)) {
6082 create_options |= FILE_DIRECTORY_FILE;
6085 status = SMB_VFS_CREATE_FILE(
6088 0, /* root_dir_fid */
6090 0, /* create_file_flags */
6091 access_mask, /* access_mask */
6092 (FILE_SHARE_READ | /* share_access */
6094 FILE_OPEN, /* create_disposition*/
6095 create_options, /* create_options */
6096 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6097 0, /* oplock_request */
6098 0, /* allocation_size */
6103 &sbuf1); /* psbuf */
6105 if (!NT_STATUS_IS_OK(status)) {
6106 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6107 "returned %s rename %s -> %s\n",
6108 nt_errstr(status), directory, newname));
6112 status = rename_internals_fsp(conn, fsp, destname, dname,
6113 attrs, replace_if_exists);
6115 close_file(req, fsp, NORMAL_CLOSE);
6117 if (!NT_STATUS_IS_OK(status)) {
6118 DEBUG(3, ("rename_internals_fsp returned %s for "
6119 "rename %s -> %s\n", nt_errstr(status),
6120 directory, newname));
6126 DEBUG(3,("rename_internals: doing rename on %s -> "
6127 "%s\n",fname,destname));
6130 TALLOC_FREE(destname);
6132 TALLOC_FREE(dir_hnd);
6134 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6135 status = map_nt_error_from_unix(errno);
6141 /****************************************************************************
6143 ****************************************************************************/
6145 void reply_mv(struct smb_request *req)
6147 connection_struct *conn = req->conn;
6149 char *newname = NULL;
6153 bool src_has_wcard = False;
6154 bool dest_has_wcard = False;
6155 TALLOC_CTX *ctx = talloc_tos();
6157 START_PROFILE(SMBmv);
6160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6165 attrs = SVAL(req->vwv+0, 0);
6167 p = (const char *)req->buf + 1;
6168 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6169 &status, &src_has_wcard);
6170 if (!NT_STATUS_IS_OK(status)) {
6171 reply_nterror(req, status);
6176 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6177 &status, &dest_has_wcard);
6178 if (!NT_STATUS_IS_OK(status)) {
6179 reply_nterror(req, status);
6184 status = resolve_dfspath_wcard(ctx, conn,
6185 req->flags2 & FLAGS2_DFS_PATHNAMES,
6189 if (!NT_STATUS_IS_OK(status)) {
6190 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6191 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6192 ERRSRV, ERRbadpath);
6196 reply_nterror(req, status);
6201 status = resolve_dfspath_wcard(ctx, conn,
6202 req->flags2 & FLAGS2_DFS_PATHNAMES,
6206 if (!NT_STATUS_IS_OK(status)) {
6207 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6208 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6209 ERRSRV, ERRbadpath);
6213 reply_nterror(req, status);
6218 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6220 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6221 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6222 if (!NT_STATUS_IS_OK(status)) {
6223 if (open_was_deferred(req->mid)) {
6224 /* We have re-scheduled this call. */
6228 reply_nterror(req, status);
6233 reply_outbuf(req, 0, 0);
6239 /*******************************************************************
6240 Copy a file as part of a reply_copy.
6241 ******************************************************************/
6244 * TODO: check error codes on all callers
6247 NTSTATUS copy_file(TALLOC_CTX *ctx,
6248 connection_struct *conn,
6253 bool target_is_directory)
6255 SMB_STRUCT_STAT src_sbuf, sbuf2;
6257 files_struct *fsp1,*fsp2;
6260 uint32 new_create_disposition;
6263 dest = talloc_strdup(ctx, dest1);
6265 return NT_STATUS_NO_MEMORY;
6267 if (target_is_directory) {
6268 const char *p = strrchr_m(src,'/');
6274 dest = talloc_asprintf_append(dest,
6278 return NT_STATUS_NO_MEMORY;
6282 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6284 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6287 if (!target_is_directory && count) {
6288 new_create_disposition = FILE_OPEN;
6290 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6291 NULL, NULL, &new_create_disposition, NULL)) {
6293 return NT_STATUS_INVALID_PARAMETER;
6297 status = SMB_VFS_CREATE_FILE(
6300 0, /* root_dir_fid */
6302 0, /* create_file_flags */
6303 FILE_GENERIC_READ, /* access_mask */
6304 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6305 FILE_OPEN, /* create_disposition*/
6306 0, /* create_options */
6307 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6308 INTERNAL_OPEN_ONLY, /* oplock_request */
6309 0, /* allocation_size */
6314 &src_sbuf); /* psbuf */
6316 if (!NT_STATUS_IS_OK(status)) {
6321 dosattrs = dos_mode(conn, src, &src_sbuf);
6322 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6323 ZERO_STRUCTP(&sbuf2);
6326 status = SMB_VFS_CREATE_FILE(
6329 0, /* root_dir_fid */
6331 0, /* create_file_flags */
6332 FILE_GENERIC_WRITE, /* access_mask */
6333 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6334 new_create_disposition, /* create_disposition*/
6335 0, /* create_options */
6336 dosattrs, /* file_attributes */
6337 INTERNAL_OPEN_ONLY, /* oplock_request */
6338 0, /* allocation_size */
6343 &sbuf2); /* psbuf */
6347 if (!NT_STATUS_IS_OK(status)) {
6348 close_file(NULL, fsp1, ERROR_CLOSE);
6352 if ((ofun&3) == 1) {
6353 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6354 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6356 * Stop the copy from occurring.
6359 src_sbuf.st_size = 0;
6363 if (src_sbuf.st_size) {
6364 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6367 close_file(NULL, fsp1, NORMAL_CLOSE);
6369 /* Ensure the modtime is set correctly on the destination file. */
6370 set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
6373 * As we are opening fsp1 read-only we only expect
6374 * an error on close on fsp2 if we are out of space.
6375 * Thus we don't look at the error return from the
6378 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6380 if (!NT_STATUS_IS_OK(status)) {
6384 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6385 return NT_STATUS_DISK_FULL;
6388 return NT_STATUS_OK;
6391 /****************************************************************************
6392 Reply to a file copy.
6393 ****************************************************************************/
6395 void reply_copy(struct smb_request *req)
6397 connection_struct *conn = req->conn;
6399 char *newname = NULL;
6400 char *directory = NULL;
6401 const char *mask = NULL;
6402 const char mask_star[] = "*";
6405 int error = ERRnoaccess;
6410 bool target_is_directory=False;
6411 bool source_has_wild = False;
6412 bool dest_has_wild = False;
6413 SMB_STRUCT_STAT sbuf1, sbuf2;
6415 TALLOC_CTX *ctx = talloc_tos();
6417 START_PROFILE(SMBcopy);
6420 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6421 END_PROFILE(SMBcopy);
6425 tid2 = SVAL(req->vwv+0, 0);
6426 ofun = SVAL(req->vwv+1, 0);
6427 flags = SVAL(req->vwv+2, 0);
6429 p = (const char *)req->buf;
6430 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6431 &status, &source_has_wild);
6432 if (!NT_STATUS_IS_OK(status)) {
6433 reply_nterror(req, status);
6434 END_PROFILE(SMBcopy);
6437 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6438 &status, &dest_has_wild);
6439 if (!NT_STATUS_IS_OK(status)) {
6440 reply_nterror(req, status);
6441 END_PROFILE(SMBcopy);
6445 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6447 if (tid2 != conn->cnum) {
6448 /* can't currently handle inter share copies XXXX */
6449 DEBUG(3,("Rejecting inter-share copy\n"));
6450 reply_doserror(req, ERRSRV, ERRinvdevice);
6451 END_PROFILE(SMBcopy);
6455 status = resolve_dfspath_wcard(ctx, conn,
6456 req->flags2 & FLAGS2_DFS_PATHNAMES,
6460 if (!NT_STATUS_IS_OK(status)) {
6461 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6462 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6463 ERRSRV, ERRbadpath);
6464 END_PROFILE(SMBcopy);
6467 reply_nterror(req, status);
6468 END_PROFILE(SMBcopy);
6472 status = resolve_dfspath_wcard(ctx, conn,
6473 req->flags2 & FLAGS2_DFS_PATHNAMES,
6477 if (!NT_STATUS_IS_OK(status)) {
6478 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6479 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6480 ERRSRV, ERRbadpath);
6481 END_PROFILE(SMBcopy);
6484 reply_nterror(req, status);
6485 END_PROFILE(SMBcopy);
6489 status = unix_convert(ctx, conn, name, source_has_wild,
6490 &name, NULL, &sbuf1);
6491 if (!NT_STATUS_IS_OK(status)) {
6492 reply_nterror(req, status);
6493 END_PROFILE(SMBcopy);
6497 status = unix_convert(ctx, conn, newname, dest_has_wild,
6498 &newname, NULL, &sbuf2);
6499 if (!NT_STATUS_IS_OK(status)) {
6500 reply_nterror(req, status);
6501 END_PROFILE(SMBcopy);
6505 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6507 if ((flags&1) && target_is_directory) {
6508 reply_doserror(req, ERRDOS, ERRbadfile);
6509 END_PROFILE(SMBcopy);
6513 if ((flags&2) && !target_is_directory) {
6514 reply_doserror(req, ERRDOS, ERRbadpath);
6515 END_PROFILE(SMBcopy);
6519 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6520 /* wants a tree copy! XXXX */
6521 DEBUG(3,("Rejecting tree copy\n"));
6522 reply_doserror(req, ERRSRV, ERRerror);
6523 END_PROFILE(SMBcopy);
6527 p = strrchr_m(name,'/');
6529 directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
6532 directory = talloc_strdup(ctx, "./");
6537 reply_nterror(req, NT_STATUS_NO_MEMORY);
6538 END_PROFILE(SMBcopy);
6543 * We should only check the mangled cache
6544 * here if unix_convert failed. This means
6545 * that the path in 'mask' doesn't exist
6546 * on the file system and so we need to look
6547 * for a possible mangle. This patch from
6548 * Tine Smukavec <valentin.smukavec@hermes.si>.
6551 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6552 char *new_mask = NULL;
6553 mangle_lookup_name_from_8_3(ctx,
6562 if (!source_has_wild) {
6563 directory = talloc_asprintf_append(directory,
6566 if (dest_has_wild) {
6567 char *mod_newname = NULL;
6568 if (!resolve_wildcards(ctx,
6569 directory,newname,&mod_newname)) {
6570 reply_nterror(req, NT_STATUS_NO_MEMORY);
6571 END_PROFILE(SMBcopy);
6574 newname = mod_newname;
6577 status = check_name(conn, directory);
6578 if (!NT_STATUS_IS_OK(status)) {
6579 reply_nterror(req, status);
6580 END_PROFILE(SMBcopy);
6584 status = check_name(conn, newname);
6585 if (!NT_STATUS_IS_OK(status)) {
6586 reply_nterror(req, status);
6587 END_PROFILE(SMBcopy);
6591 status = copy_file(ctx,conn,directory,newname,ofun,
6592 count,target_is_directory);
6594 if(!NT_STATUS_IS_OK(status)) {
6595 reply_nterror(req, status);
6596 END_PROFILE(SMBcopy);
6602 struct smb_Dir *dir_hnd = NULL;
6603 const char *dname = NULL;
6606 if (strequal(mask,"????????.???")) {
6610 status = check_name(conn, directory);
6611 if (!NT_STATUS_IS_OK(status)) {
6612 reply_nterror(req, status);
6613 END_PROFILE(SMBcopy);
6617 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6618 if (dir_hnd == NULL) {
6619 status = map_nt_error_from_unix(errno);
6620 reply_nterror(req, status);
6621 END_PROFILE(SMBcopy);
6627 while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
6628 char *destname = NULL;
6631 if (ISDOT(dname) || ISDOTDOT(dname)) {
6635 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6639 if(!mask_match(dname, mask, conn->case_sensitive)) {
6643 error = ERRnoaccess;
6644 fname = talloc_asprintf(ctx,
6649 TALLOC_FREE(dir_hnd);
6650 reply_nterror(req, NT_STATUS_NO_MEMORY);
6651 END_PROFILE(SMBcopy);
6655 if (!resolve_wildcards(ctx,
6656 fname,newname,&destname)) {
6660 TALLOC_FREE(dir_hnd);
6661 reply_nterror(req, NT_STATUS_NO_MEMORY);
6662 END_PROFILE(SMBcopy);
6666 status = check_name(conn, fname);
6667 if (!NT_STATUS_IS_OK(status)) {
6668 TALLOC_FREE(dir_hnd);
6669 reply_nterror(req, status);
6670 END_PROFILE(SMBcopy);
6674 status = check_name(conn, destname);
6675 if (!NT_STATUS_IS_OK(status)) {
6676 TALLOC_FREE(dir_hnd);
6677 reply_nterror(req, status);
6678 END_PROFILE(SMBcopy);
6682 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6684 status = copy_file(ctx,conn,fname,destname,ofun,
6685 count,target_is_directory);
6686 if (NT_STATUS_IS_OK(status)) {
6690 TALLOC_FREE(destname);
6692 TALLOC_FREE(dir_hnd);
6697 /* Error on close... */
6699 reply_unixerror(req, ERRHRD, ERRgeneral);
6700 END_PROFILE(SMBcopy);
6704 reply_doserror(req, ERRDOS, error);
6705 END_PROFILE(SMBcopy);
6709 reply_outbuf(req, 1, 0);
6710 SSVAL(req->outbuf,smb_vwv0,count);
6712 END_PROFILE(SMBcopy);
6717 #define DBGC_CLASS DBGC_LOCKING
6719 /****************************************************************************
6720 Get a lock pid, dealing with large count requests.
6721 ****************************************************************************/
6723 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6724 bool large_file_format)
6726 if(!large_file_format)
6727 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6729 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6732 /****************************************************************************
6733 Get a lock count, dealing with large count requests.
6734 ****************************************************************************/
6736 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6737 bool large_file_format)
6741 if(!large_file_format) {
6742 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6745 #if defined(HAVE_LONGLONG)
6746 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6747 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6748 #else /* HAVE_LONGLONG */
6751 * NT4.x seems to be broken in that it sends large file (64 bit)
6752 * lockingX calls even if the CAP_LARGE_FILES was *not*
6753 * negotiated. For boxes without large unsigned ints truncate the
6754 * lock count by dropping the top 32 bits.
6757 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6758 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6759 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6760 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6761 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6764 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6765 #endif /* HAVE_LONGLONG */
6771 #if !defined(HAVE_LONGLONG)
6772 /****************************************************************************
6773 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6774 ****************************************************************************/
6776 static uint32 map_lock_offset(uint32 high, uint32 low)
6780 uint32 highcopy = high;
6783 * Try and find out how many significant bits there are in high.
6786 for(i = 0; highcopy; i++)
6790 * We use 31 bits not 32 here as POSIX
6791 * lock offsets may not be negative.
6794 mask = (~0) << (31 - i);
6797 return 0; /* Fail. */
6803 #endif /* !defined(HAVE_LONGLONG) */
6805 /****************************************************************************
6806 Get a lock offset, dealing with large offset requests.
6807 ****************************************************************************/
6809 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6810 bool large_file_format, bool *err)
6812 uint64_t offset = 0;
6816 if(!large_file_format) {
6817 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6820 #if defined(HAVE_LONGLONG)
6821 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6822 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6823 #else /* HAVE_LONGLONG */
6826 * NT4.x seems to be broken in that it sends large file (64 bit)
6827 * lockingX calls even if the CAP_LARGE_FILES was *not*
6828 * negotiated. For boxes without large unsigned ints mangle the
6829 * lock offset by mapping the top 32 bits onto the lower 32.
6832 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6833 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6834 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6837 if((new_low = map_lock_offset(high, low)) == 0) {
6839 return (uint64_t)-1;
6842 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6843 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6844 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6845 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6848 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6849 #endif /* HAVE_LONGLONG */
6855 /****************************************************************************
6856 Reply to a lockingX request.
6857 ****************************************************************************/
6859 void reply_lockingX(struct smb_request *req)
6861 connection_struct *conn = req->conn;
6863 unsigned char locktype;
6864 unsigned char oplocklevel;
6867 uint64_t count = 0, offset = 0;
6871 const uint8_t *data;
6872 bool large_file_format;
6874 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6876 START_PROFILE(SMBlockingX);
6879 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6880 END_PROFILE(SMBlockingX);
6884 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
6885 locktype = CVAL(req->vwv+3, 0);
6886 oplocklevel = CVAL(req->vwv+3, 1);
6887 num_ulocks = SVAL(req->vwv+6, 0);
6888 num_locks = SVAL(req->vwv+7, 0);
6889 lock_timeout = IVAL(req->vwv+4, 0);
6890 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6892 if (!check_fsp(conn, req, fsp)) {
6893 END_PROFILE(SMBlockingX);
6899 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6900 /* we don't support these - and CANCEL_LOCK makes w2k
6901 and XP reboot so I don't really want to be
6902 compatible! (tridge) */
6903 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6904 END_PROFILE(SMBlockingX);
6908 /* Check if this is an oplock break on a file
6909 we have granted an oplock on.
6911 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6912 /* Client can insist on breaking to none. */
6913 bool break_to_none = (oplocklevel == 0);
6916 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6917 "for fnum = %d\n", (unsigned int)oplocklevel,
6921 * Make sure we have granted an exclusive or batch oplock on
6925 if (fsp->oplock_type == 0) {
6927 /* The Samba4 nbench simulator doesn't understand
6928 the difference between break to level2 and break
6929 to none from level2 - it sends oplock break
6930 replies in both cases. Don't keep logging an error
6931 message here - just ignore it. JRA. */
6933 DEBUG(5,("reply_lockingX: Error : oplock break from "
6934 "client for fnum = %d (oplock=%d) and no "
6935 "oplock granted on this file (%s).\n",
6936 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
6938 /* if this is a pure oplock break request then don't
6940 if (num_locks == 0 && num_ulocks == 0) {
6941 END_PROFILE(SMBlockingX);
6944 END_PROFILE(SMBlockingX);
6945 reply_doserror(req, ERRDOS, ERRlock);
6950 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6952 result = remove_oplock(fsp);
6954 result = downgrade_oplock(fsp);
6958 DEBUG(0, ("reply_lockingX: error in removing "
6959 "oplock on file %s\n", fsp->fsp_name));
6960 /* Hmmm. Is this panic justified? */
6961 smb_panic("internal tdb error");
6964 reply_to_oplock_break_requests(fsp);
6966 /* if this is a pure oplock break request then don't send a
6968 if (num_locks == 0 && num_ulocks == 0) {
6969 /* Sanity check - ensure a pure oplock break is not a
6971 if(CVAL(req->vwv+0, 0) != 0xff)
6972 DEBUG(0,("reply_lockingX: Error : pure oplock "
6973 "break is a chained %d request !\n",
6974 (unsigned int)CVAL(req->vwv+0, 0)));
6975 END_PROFILE(SMBlockingX);
6981 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6983 END_PROFILE(SMBlockingX);
6987 /* Data now points at the beginning of the list
6988 of smb_unlkrng structs */
6989 for(i = 0; i < (int)num_ulocks; i++) {
6990 lock_pid = get_lock_pid( data, i, large_file_format);
6991 count = get_lock_count( data, i, large_file_format);
6992 offset = get_lock_offset( data, i, large_file_format, &err);
6995 * There is no error code marked "stupid client bug".... :-).
6998 END_PROFILE(SMBlockingX);
6999 reply_doserror(req, ERRDOS, ERRnoaccess);
7003 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
7004 "pid %u, file %s\n", (double)offset, (double)count,
7005 (unsigned int)lock_pid, fsp->fsp_name ));
7007 status = do_unlock(smbd_messaging_context(),
7014 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
7015 nt_errstr(status)));
7017 if (NT_STATUS_V(status)) {
7018 END_PROFILE(SMBlockingX);
7019 reply_nterror(req, status);
7024 /* Setup the timeout in seconds. */
7026 if (!lp_blocking_locks(SNUM(conn))) {
7030 /* Now do any requested locks */
7031 data += ((large_file_format ? 20 : 10)*num_ulocks);
7033 /* Data now points at the beginning of the list
7034 of smb_lkrng structs */
7036 for(i = 0; i < (int)num_locks; i++) {
7037 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
7038 READ_LOCK:WRITE_LOCK);
7039 lock_pid = get_lock_pid( data, i, large_file_format);
7040 count = get_lock_count( data, i, large_file_format);
7041 offset = get_lock_offset( data, i, large_file_format, &err);
7044 * There is no error code marked "stupid client bug".... :-).
7047 END_PROFILE(SMBlockingX);
7048 reply_doserror(req, ERRDOS, ERRnoaccess);
7052 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
7053 "%u, file %s timeout = %d\n", (double)offset,
7054 (double)count, (unsigned int)lock_pid,
7055 fsp->fsp_name, (int)lock_timeout ));
7057 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7058 struct blocking_lock_record *blr = NULL;
7060 if (lp_blocking_locks(SNUM(conn))) {
7062 /* Schedule a message to ourselves to
7063 remove the blocking lock record and
7064 return the right error. */
7066 blr = blocking_lock_cancel(fsp,
7072 NT_STATUS_FILE_LOCK_CONFLICT);
7074 END_PROFILE(SMBlockingX);
7079 ERRcancelviolation));
7083 /* Remove a matching pending lock. */
7084 status = do_lock_cancel(fsp,
7091 bool blocking_lock = lock_timeout ? True : False;
7092 bool defer_lock = False;
7093 struct byte_range_lock *br_lck;
7094 uint32 block_smbpid;
7096 br_lck = do_lock(smbd_messaging_context(),
7108 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7109 /* Windows internal resolution for blocking locks seems
7110 to be about 200ms... Don't wait for less than that. JRA. */
7111 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7112 lock_timeout = lp_lock_spin_time();
7117 /* This heuristic seems to match W2K3 very well. If a
7118 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7119 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7120 far as I can tell. Replacement for do_lock_spin(). JRA. */
7122 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7123 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7125 lock_timeout = lp_lock_spin_time();
7128 if (br_lck && defer_lock) {
7130 * A blocking lock was requested. Package up
7131 * this smb into a queued request and push it
7132 * onto the blocking lock queue.
7134 if(push_blocking_lock_request(br_lck,
7145 TALLOC_FREE(br_lck);
7146 END_PROFILE(SMBlockingX);
7151 TALLOC_FREE(br_lck);
7154 if (NT_STATUS_V(status)) {
7155 END_PROFILE(SMBlockingX);
7156 reply_nterror(req, status);
7161 /* If any of the above locks failed, then we must unlock
7162 all of the previous locks (X/Open spec). */
7164 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7168 * Ensure we don't do a remove on the lock that just failed,
7169 * as under POSIX rules, if we have a lock already there, we
7170 * will delete it (and we shouldn't) .....
7172 for(i--; i >= 0; i--) {
7173 lock_pid = get_lock_pid( data, i, large_file_format);
7174 count = get_lock_count( data, i, large_file_format);
7175 offset = get_lock_offset( data, i, large_file_format,
7179 * There is no error code marked "stupid client
7183 END_PROFILE(SMBlockingX);
7184 reply_doserror(req, ERRDOS, ERRnoaccess);
7188 do_unlock(smbd_messaging_context(),
7195 END_PROFILE(SMBlockingX);
7196 reply_nterror(req, status);
7200 reply_outbuf(req, 2, 0);
7202 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7203 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7205 END_PROFILE(SMBlockingX);
7210 #define DBGC_CLASS DBGC_ALL
7212 /****************************************************************************
7213 Reply to a SMBreadbmpx (read block multiplex) request.
7214 Always reply with an error, if someone has a platform really needs this,
7215 please contact vl@samba.org
7216 ****************************************************************************/
7218 void reply_readbmpx(struct smb_request *req)
7220 START_PROFILE(SMBreadBmpx);
7221 reply_doserror(req, ERRSRV, ERRuseSTD);
7222 END_PROFILE(SMBreadBmpx);
7226 /****************************************************************************
7227 Reply to a SMBreadbs (read block multiplex secondary) request.
7228 Always reply with an error, if someone has a platform really needs this,
7229 please contact vl@samba.org
7230 ****************************************************************************/
7232 void reply_readbs(struct smb_request *req)
7234 START_PROFILE(SMBreadBs);
7235 reply_doserror(req, ERRSRV, ERRuseSTD);
7236 END_PROFILE(SMBreadBs);
7240 /****************************************************************************
7241 Reply to a SMBsetattrE.
7242 ****************************************************************************/
7244 void reply_setattrE(struct smb_request *req)
7246 connection_struct *conn = req->conn;
7247 struct smb_file_time ft;
7249 SMB_STRUCT_STAT sbuf;
7252 START_PROFILE(SMBsetattrE);
7256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7257 END_PROFILE(SMBsetattrE);
7261 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7263 if(!fsp || (fsp->conn != conn)) {
7264 reply_doserror(req, ERRDOS, ERRbadfid);
7265 END_PROFILE(SMBsetattrE);
7271 * Convert the DOS times into unix times.
7274 ft.atime = convert_time_t_to_timespec(
7275 srv_make_unix_date2(req->vwv+3));
7276 ft.mtime = convert_time_t_to_timespec(
7277 srv_make_unix_date2(req->vwv+5));
7278 ft.create_time = convert_time_t_to_timespec(
7279 srv_make_unix_date2(req->vwv+1));
7281 reply_outbuf(req, 0, 0);
7284 * Patch from Ray Frush <frush@engr.colostate.edu>
7285 * Sometimes times are sent as zero - ignore them.
7288 /* Ensure we have a valid stat struct for the source. */
7289 if (fsp->fh->fd != -1) {
7290 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7291 status = map_nt_error_from_unix(errno);
7292 reply_nterror(req, status);
7293 END_PROFILE(SMBsetattrE);
7299 if (fsp->posix_open) {
7300 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
7302 ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
7305 status = map_nt_error_from_unix(errno);
7306 reply_nterror(req, status);
7307 END_PROFILE(SMBsetattrE);
7312 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7314 if (!NT_STATUS_IS_OK(status)) {
7315 reply_doserror(req, ERRDOS, ERRnoaccess);
7316 END_PROFILE(SMBsetattrE);
7320 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7323 (unsigned int)ft.atime.tv_sec,
7324 (unsigned int)ft.mtime.tv_sec,
7325 (unsigned int)ft.create_time.tv_sec
7328 END_PROFILE(SMBsetattrE);
7333 /* Back from the dead for OS/2..... JRA. */
7335 /****************************************************************************
7336 Reply to a SMBwritebmpx (write block multiplex primary) request.
7337 Always reply with an error, if someone has a platform really needs this,
7338 please contact vl@samba.org
7339 ****************************************************************************/
7341 void reply_writebmpx(struct smb_request *req)
7343 START_PROFILE(SMBwriteBmpx);
7344 reply_doserror(req, ERRSRV, ERRuseSTD);
7345 END_PROFILE(SMBwriteBmpx);
7349 /****************************************************************************
7350 Reply to a SMBwritebs (write block multiplex secondary) request.
7351 Always reply with an error, if someone has a platform really needs this,
7352 please contact vl@samba.org
7353 ****************************************************************************/
7355 void reply_writebs(struct smb_request *req)
7357 START_PROFILE(SMBwriteBs);
7358 reply_doserror(req, ERRSRV, ERRuseSTD);
7359 END_PROFILE(SMBwriteBs);
7363 /****************************************************************************
7364 Reply to a SMBgetattrE.
7365 ****************************************************************************/
7367 void reply_getattrE(struct smb_request *req)
7369 connection_struct *conn = req->conn;
7370 SMB_STRUCT_STAT sbuf;
7373 struct timespec create_ts;
7375 START_PROFILE(SMBgetattrE);
7378 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7379 END_PROFILE(SMBgetattrE);
7383 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7385 if(!fsp || (fsp->conn != conn)) {
7386 reply_doserror(req, ERRDOS, ERRbadfid);
7387 END_PROFILE(SMBgetattrE);
7391 /* Do an fstat on this file */
7392 if(fsp_stat(fsp, &sbuf)) {
7393 reply_unixerror(req, ERRDOS, ERRnoaccess);
7394 END_PROFILE(SMBgetattrE);
7398 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7401 * Convert the times into dos times. Set create
7402 * date to be last modify date as UNIX doesn't save
7406 reply_outbuf(req, 11, 0);
7408 create_ts = get_create_timespec(&sbuf,
7409 lp_fake_dir_create_times(SNUM(conn)));
7410 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7411 srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7412 /* Should we check pending modtime here ? JRA */
7413 srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7416 SIVAL(req->outbuf, smb_vwv6, 0);
7417 SIVAL(req->outbuf, smb_vwv8, 0);
7419 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7420 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7421 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7423 SSVAL(req->outbuf,smb_vwv10, mode);
7425 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7427 END_PROFILE(SMBgetattrE);