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 static bool netbios_session_retarget(const char *name, int name_type)
413 char *trim_name_type;
414 const char *retarget_parm;
417 int retarget_type = 0x20;
418 int retarget_port = 139;
419 struct sockaddr_storage retarget_addr;
420 struct sockaddr_in *in_addr;
424 if (get_socket_port(smbd_server_fd()) != 139) {
428 trim_name = talloc_strdup(talloc_tos(), name);
429 if (trim_name == NULL) {
432 trim_char(trim_name, ' ', ' ');
434 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
436 if (trim_name_type == NULL) {
440 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
441 trim_name_type, NULL);
442 if (retarget_parm == NULL) {
443 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
446 if (retarget_parm == NULL) {
450 retarget = talloc_strdup(trim_name, retarget_parm);
451 if (retarget == NULL) {
455 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
457 p = strchr(retarget, ':');
460 retarget_port = atoi(p);
463 p = strchr_m(retarget, '#');
466 sscanf(p, "%x", &retarget_type);
469 ret = resolve_name(retarget, &retarget_addr, retarget_type);
471 DEBUG(10, ("could not resolve %s\n", retarget));
475 if (retarget_addr.ss_family != AF_INET) {
476 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
480 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
482 _smb_setlen(outbuf, 6);
483 SCVAL(outbuf, 0, 0x84);
484 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
485 *(uint16_t *)(outbuf+8) = htons(retarget_port);
487 if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
489 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
495 TALLOC_FREE(trim_name);
499 /****************************************************************************
500 Reply to a (netbios-level) special message.
501 ****************************************************************************/
503 void reply_special(char *inbuf)
505 int msg_type = CVAL(inbuf,0);
506 int msg_flags = CVAL(inbuf,1);
508 char name_type1, name_type2;
509 struct smbd_server_connection *sconn = smbd_server_conn;
512 * We only really use 4 bytes of the outbuf, but for the smb_setlen
513 * calculation & friends (srv_send_smb uses that) we need the full smb
516 char outbuf[smb_size];
520 memset(outbuf, '\0', sizeof(outbuf));
522 smb_setlen(outbuf,0);
525 case 0x81: /* session request */
527 if (sconn->nbt.got_session) {
528 exit_server_cleanly("multiple session request not permitted");
531 SCVAL(outbuf,0,0x82);
533 if (name_len(inbuf+4) > 50 ||
534 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
535 DEBUG(0,("Invalid name length in session request\n"));
538 name_type1 = name_extract(inbuf,4,name1);
539 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
540 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
541 name1, name_type1, name2, name_type2));
543 if (netbios_session_retarget(name1, name_type1)) {
544 exit_server_cleanly("retargeted client");
547 set_local_machine_name(name1, True);
548 set_remote_machine_name(name2, True);
550 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
551 get_local_machine_name(), get_remote_machine_name(),
554 if (name_type2 == 'R') {
555 /* We are being asked for a pathworks session ---
557 SCVAL(outbuf, 0,0x83);
561 /* only add the client's machine name to the list
562 of possibly valid usernames if we are operating
563 in share mode security */
564 if (lp_security() == SEC_SHARE) {
565 add_session_user(sconn, get_remote_machine_name());
568 reload_services(True);
571 sconn->nbt.got_session = true;
574 case 0x89: /* session keepalive request
575 (some old clients produce this?) */
576 SCVAL(outbuf,0,SMBkeepalive);
580 case 0x82: /* positive session response */
581 case 0x83: /* negative session response */
582 case 0x84: /* retarget session response */
583 DEBUG(0,("Unexpected session response\n"));
586 case SMBkeepalive: /* session keepalive */
591 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
592 msg_type, msg_flags));
594 srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
598 /****************************************************************************
600 conn POINTER CAN BE NULL HERE !
601 ****************************************************************************/
603 void reply_tcon(struct smb_request *req)
605 connection_struct *conn = req->conn;
607 char *service_buf = NULL;
608 char *password = NULL;
613 DATA_BLOB password_blob;
614 TALLOC_CTX *ctx = talloc_tos();
615 struct smbd_server_connection *sconn = smbd_server_conn;
617 START_PROFILE(SMBtcon);
619 if (req->buflen < 4) {
620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
621 END_PROFILE(SMBtcon);
625 p = (const char *)req->buf + 1;
626 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
628 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
630 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
633 if (service_buf == NULL || password == NULL || dev == NULL) {
634 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
635 END_PROFILE(SMBtcon);
638 p = strrchr_m(service_buf,'\\');
642 service = service_buf;
645 password_blob = data_blob(password, pwlen+1);
647 conn = make_connection(sconn,service,password_blob,dev,
648 req->vuid,&nt_status);
651 data_blob_clear_free(&password_blob);
654 reply_nterror(req, nt_status);
655 END_PROFILE(SMBtcon);
659 reply_outbuf(req, 2, 0);
660 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
661 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
662 SSVAL(req->outbuf,smb_tid,conn->cnum);
664 DEBUG(3,("tcon service=%s cnum=%d\n",
665 service, conn->cnum));
667 END_PROFILE(SMBtcon);
671 /****************************************************************************
672 Reply to a tcon and X.
673 conn POINTER CAN BE NULL HERE !
674 ****************************************************************************/
676 void reply_tcon_and_X(struct smb_request *req)
678 connection_struct *conn = req->conn;
679 const char *service = NULL;
681 TALLOC_CTX *ctx = talloc_tos();
682 /* what the cleint thinks the device is */
683 char *client_devicetype = NULL;
684 /* what the server tells the client the share represents */
685 const char *server_devicetype;
691 struct smbd_server_connection *sconn = smbd_server_conn;
693 START_PROFILE(SMBtconX);
696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
697 END_PROFILE(SMBtconX);
701 passlen = SVAL(req->vwv+3, 0);
702 tcon_flags = SVAL(req->vwv+2, 0);
704 /* we might have to close an old one */
705 if ((tcon_flags & 0x1) && conn) {
706 close_cnum(conn,req->vuid);
711 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
712 reply_doserror(req, ERRDOS, ERRbuftoosmall);
713 END_PROFILE(SMBtconX);
717 if (sconn->smb1.negprot.encrypted_passwords) {
718 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
719 if (lp_security() == SEC_SHARE) {
721 * Security = share always has a pad byte
722 * after the password.
724 p = (const char *)req->buf + passlen + 1;
726 p = (const char *)req->buf + passlen;
729 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
730 /* Ensure correct termination */
731 password.data[passlen]=0;
732 p = (const char *)req->buf + passlen + 1;
735 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
738 data_blob_clear_free(&password);
739 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
740 END_PROFILE(SMBtconX);
745 * the service name can be either: \\server\share
746 * or share directly like on the DELL PowerVault 705
749 q = strchr_m(path+2,'\\');
751 data_blob_clear_free(&password);
752 reply_doserror(req, ERRDOS, ERRnosuchshare);
753 END_PROFILE(SMBtconX);
761 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
762 &client_devicetype, p,
763 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
765 if (client_devicetype == NULL) {
766 data_blob_clear_free(&password);
767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
768 END_PROFILE(SMBtconX);
772 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
774 conn = make_connection(sconn, service, password, client_devicetype,
775 req->vuid, &nt_status);
778 data_blob_clear_free(&password);
781 reply_nterror(req, nt_status);
782 END_PROFILE(SMBtconX);
787 server_devicetype = "IPC";
788 else if ( IS_PRINT(conn) )
789 server_devicetype = "LPT1:";
791 server_devicetype = "A:";
793 if (Protocol < PROTOCOL_NT1) {
794 reply_outbuf(req, 2, 0);
795 if (message_push_string(&req->outbuf, server_devicetype,
796 STR_TERMINATE|STR_ASCII) == -1) {
797 reply_nterror(req, NT_STATUS_NO_MEMORY);
798 END_PROFILE(SMBtconX);
802 /* NT sets the fstype of IPC$ to the null string */
803 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
805 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
806 /* Return permissions. */
810 reply_outbuf(req, 7, 0);
813 perm1 = FILE_ALL_ACCESS;
814 perm2 = FILE_ALL_ACCESS;
816 perm1 = CAN_WRITE(conn) ?
821 SIVAL(req->outbuf, smb_vwv3, perm1);
822 SIVAL(req->outbuf, smb_vwv5, perm2);
824 reply_outbuf(req, 3, 0);
827 if ((message_push_string(&req->outbuf, server_devicetype,
828 STR_TERMINATE|STR_ASCII) == -1)
829 || (message_push_string(&req->outbuf, fstype,
830 STR_TERMINATE) == -1)) {
831 reply_nterror(req, NT_STATUS_NO_MEMORY);
832 END_PROFILE(SMBtconX);
836 /* what does setting this bit do? It is set by NT4 and
837 may affect the ability to autorun mounted cdroms */
838 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
839 (lp_csc_policy(SNUM(conn)) << 2));
841 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
842 DEBUG(2,("Serving %s as a Dfs root\n",
843 lp_servicename(SNUM(conn)) ));
844 SSVAL(req->outbuf, smb_vwv2,
845 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
850 DEBUG(3,("tconX service=%s \n",
853 /* set the incoming and outgoing tid to the just created one */
854 SSVAL(req->inbuf,smb_tid,conn->cnum);
855 SSVAL(req->outbuf,smb_tid,conn->cnum);
857 END_PROFILE(SMBtconX);
863 /****************************************************************************
864 Reply to an unknown type.
865 ****************************************************************************/
867 void reply_unknown_new(struct smb_request *req, uint8 type)
869 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
870 smb_fn_name(type), type, type));
871 reply_doserror(req, ERRSRV, ERRunknownsmb);
875 /****************************************************************************
877 conn POINTER CAN BE NULL HERE !
878 ****************************************************************************/
880 void reply_ioctl(struct smb_request *req)
882 connection_struct *conn = req->conn;
889 START_PROFILE(SMBioctl);
892 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
893 END_PROFILE(SMBioctl);
897 device = SVAL(req->vwv+1, 0);
898 function = SVAL(req->vwv+2, 0);
899 ioctl_code = (device << 16) + function;
901 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
903 switch (ioctl_code) {
904 case IOCTL_QUERY_JOB_INFO:
908 reply_doserror(req, ERRSRV, ERRnosupport);
909 END_PROFILE(SMBioctl);
913 reply_outbuf(req, 8, replysize+1);
914 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
915 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
916 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
917 p = smb_buf(req->outbuf);
918 memset(p, '\0', replysize+1); /* valgrind-safe. */
919 p += 1; /* Allow for alignment */
921 switch (ioctl_code) {
922 case IOCTL_QUERY_JOB_INFO:
924 files_struct *fsp = file_fsp(
925 req, SVAL(req->vwv+0, 0));
927 reply_doserror(req, ERRDOS, ERRbadfid);
928 END_PROFILE(SMBioctl);
931 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
932 srvstr_push((char *)req->outbuf, req->flags2, p+2,
934 STR_TERMINATE|STR_ASCII);
936 srvstr_push((char *)req->outbuf, req->flags2,
937 p+18, lp_servicename(SNUM(conn)),
938 13, STR_TERMINATE|STR_ASCII);
946 END_PROFILE(SMBioctl);
950 /****************************************************************************
951 Strange checkpath NTSTATUS mapping.
952 ****************************************************************************/
954 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
956 /* Strange DOS error code semantics only for checkpath... */
957 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
958 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
959 /* We need to map to ERRbadpath */
960 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
966 /****************************************************************************
967 Reply to a checkpath.
968 ****************************************************************************/
970 void reply_checkpath(struct smb_request *req)
972 connection_struct *conn = req->conn;
973 struct smb_filename *smb_fname = NULL;
976 TALLOC_CTX *ctx = talloc_tos();
978 START_PROFILE(SMBcheckpath);
980 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
981 STR_TERMINATE, &status);
983 if (!NT_STATUS_IS_OK(status)) {
984 status = map_checkpath_error(req->flags2, status);
985 reply_nterror(req, status);
986 END_PROFILE(SMBcheckpath);
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(SMBcheckpath);
1004 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1006 status = unix_convert(ctx, conn, name, &smb_fname, 0);
1007 if (!NT_STATUS_IS_OK(status)) {
1011 status = get_full_smb_filename(ctx, smb_fname, &name);
1012 if (!NT_STATUS_IS_OK(status)) {
1016 status = check_name(conn, name);
1017 if (!NT_STATUS_IS_OK(status)) {
1018 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
1022 if (!VALID_STAT(smb_fname->st) &&
1023 (SMB_VFS_STAT(conn, name, &smb_fname->st) != 0)) {
1024 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
1025 status = map_nt_error_from_unix(errno);
1029 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1030 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1031 ERRDOS, ERRbadpath);
1035 reply_outbuf(req, 0, 0);
1037 TALLOC_FREE(smb_fname);
1038 END_PROFILE(SMBcheckpath);
1043 TALLOC_FREE(smb_fname);
1045 END_PROFILE(SMBcheckpath);
1047 /* We special case this - as when a Windows machine
1048 is parsing a path is steps through the components
1049 one at a time - if a component fails it expects
1050 ERRbadpath, not ERRbadfile.
1052 status = map_checkpath_error(req->flags2, status);
1053 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1055 * Windows returns different error codes if
1056 * the parent directory is valid but not the
1057 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1058 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1059 * if the path is invalid.
1061 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1062 ERRDOS, ERRbadpath);
1066 reply_nterror(req, status);
1069 /****************************************************************************
1071 ****************************************************************************/
1073 void reply_getatr(struct smb_request *req)
1075 connection_struct *conn = req->conn;
1076 struct smb_filename *smb_fname = NULL;
1083 TALLOC_CTX *ctx = talloc_tos();
1085 START_PROFILE(SMBgetatr);
1087 p = (const char *)req->buf + 1;
1088 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1089 if (!NT_STATUS_IS_OK(status)) {
1090 reply_nterror(req, status);
1094 status = resolve_dfspath(ctx, conn,
1095 req->flags2 & FLAGS2_DFS_PATHNAMES,
1098 if (!NT_STATUS_IS_OK(status)) {
1099 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1100 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1101 ERRSRV, ERRbadpath);
1104 reply_nterror(req, status);
1108 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1109 under WfWg - weird! */
1110 if (*fname == '\0') {
1111 mode = aHIDDEN | aDIR;
1112 if (!CAN_WRITE(conn)) {
1118 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1119 if (!NT_STATUS_IS_OK(status)) {
1120 reply_nterror(req, status);
1123 status = get_full_smb_filename(ctx, smb_fname, &fname);
1124 if (!NT_STATUS_IS_OK(status)) {
1125 reply_nterror(req, status);
1128 status = check_name(conn, fname);
1129 if (!NT_STATUS_IS_OK(status)) {
1130 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1131 reply_nterror(req, status);
1134 if (!VALID_STAT(smb_fname->st) &&
1135 (SMB_VFS_STAT(conn, fname, &smb_fname->st) != 0)) {
1136 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1137 reply_unixerror(req, ERRDOS,ERRbadfile);
1141 mode = dos_mode(conn, fname, &smb_fname->st);
1142 size = smb_fname->st.st_ex_size;
1143 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1149 reply_outbuf(req, 10, 0);
1151 SSVAL(req->outbuf,smb_vwv0,mode);
1152 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1153 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1155 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1157 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1159 if (Protocol >= PROTOCOL_NT1) {
1160 SSVAL(req->outbuf, smb_flg2,
1161 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1164 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1167 TALLOC_FREE(smb_fname);
1168 END_PROFILE(SMBgetatr);
1172 /****************************************************************************
1174 ****************************************************************************/
1176 void reply_setatr(struct smb_request *req)
1178 struct smb_file_time ft;
1179 connection_struct *conn = req->conn;
1180 struct smb_filename *smb_fname = NULL;
1186 TALLOC_CTX *ctx = talloc_tos();
1188 START_PROFILE(SMBsetatr);
1193 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1197 p = (const char *)req->buf + 1;
1198 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1199 if (!NT_STATUS_IS_OK(status)) {
1200 reply_nterror(req, status);
1204 status = resolve_dfspath(ctx, conn,
1205 req->flags2 & FLAGS2_DFS_PATHNAMES,
1208 if (!NT_STATUS_IS_OK(status)) {
1209 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1210 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1211 ERRSRV, ERRbadpath);
1214 reply_nterror(req, status);
1218 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1219 if (!NT_STATUS_IS_OK(status)) {
1220 reply_nterror(req, status);
1224 status = get_full_smb_filename(ctx, smb_fname, &fname);
1225 if (!NT_STATUS_IS_OK(status)) {
1226 reply_nterror(req, status);
1230 status = check_name(conn, fname);
1231 if (!NT_STATUS_IS_OK(status)) {
1232 reply_nterror(req, status);
1236 if (fname[0] == '.' && fname[1] == '\0') {
1238 * Not sure here is the right place to catch this
1239 * condition. Might be moved to somewhere else later -- vl
1241 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1245 mode = SVAL(req->vwv+0, 0);
1246 mtime = srv_make_unix_date3(req->vwv+1);
1248 ft.mtime = convert_time_t_to_timespec(mtime);
1249 status = smb_set_file_time(conn, NULL, fname,
1250 &smb_fname->st, &ft, true);
1251 if (!NT_STATUS_IS_OK(status)) {
1252 reply_unixerror(req, ERRDOS, ERRnoaccess);
1256 if (mode != FILE_ATTRIBUTE_NORMAL) {
1257 if (VALID_STAT_OF_DIR(smb_fname->st))
1262 if (file_set_dosmode(conn, fname, mode, &smb_fname->st, NULL,
1264 reply_unixerror(req, ERRDOS, ERRnoaccess);
1269 reply_outbuf(req, 0, 0);
1271 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1273 TALLOC_FREE(smb_fname);
1274 END_PROFILE(SMBsetatr);
1278 /****************************************************************************
1280 ****************************************************************************/
1282 void reply_dskattr(struct smb_request *req)
1284 connection_struct *conn = req->conn;
1285 uint64_t dfree,dsize,bsize;
1286 START_PROFILE(SMBdskattr);
1288 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1289 reply_unixerror(req, ERRHRD, ERRgeneral);
1290 END_PROFILE(SMBdskattr);
1294 reply_outbuf(req, 5, 0);
1296 if (Protocol <= PROTOCOL_LANMAN2) {
1297 double total_space, free_space;
1298 /* we need to scale this to a number that DOS6 can handle. We
1299 use floating point so we can handle large drives on systems
1300 that don't have 64 bit integers
1302 we end up displaying a maximum of 2G to DOS systems
1304 total_space = dsize * (double)bsize;
1305 free_space = dfree * (double)bsize;
1307 dsize = (uint64_t)((total_space+63*512) / (64*512));
1308 dfree = (uint64_t)((free_space+63*512) / (64*512));
1310 if (dsize > 0xFFFF) dsize = 0xFFFF;
1311 if (dfree > 0xFFFF) dfree = 0xFFFF;
1313 SSVAL(req->outbuf,smb_vwv0,dsize);
1314 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1315 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1316 SSVAL(req->outbuf,smb_vwv3,dfree);
1318 SSVAL(req->outbuf,smb_vwv0,dsize);
1319 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1320 SSVAL(req->outbuf,smb_vwv2,512);
1321 SSVAL(req->outbuf,smb_vwv3,dfree);
1324 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1326 END_PROFILE(SMBdskattr);
1330 /****************************************************************************
1332 Can be called from SMBsearch, SMBffirst or SMBfunique.
1333 ****************************************************************************/
1335 void reply_search(struct smb_request *req)
1337 connection_struct *conn = req->conn;
1338 const char *mask = NULL;
1339 char *directory = NULL;
1343 struct timespec date;
1345 unsigned int numentries = 0;
1346 unsigned int maxentries = 0;
1347 bool finished = False;
1353 bool check_descend = False;
1354 bool expect_close = False;
1356 bool mask_contains_wcard = False;
1357 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1358 TALLOC_CTX *ctx = talloc_tos();
1359 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1361 START_PROFILE(SMBsearch);
1364 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1365 END_PROFILE(SMBsearch);
1369 if (lp_posix_pathnames()) {
1370 reply_unknown_new(req, req->cmd);
1371 END_PROFILE(SMBsearch);
1375 /* If we were called as SMBffirst then we must expect close. */
1376 if(req->cmd == SMBffirst) {
1377 expect_close = True;
1380 reply_outbuf(req, 1, 3);
1381 maxentries = SVAL(req->vwv+0, 0);
1382 dirtype = SVAL(req->vwv+1, 0);
1383 p = (const char *)req->buf + 1;
1384 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1385 &nt_status, &mask_contains_wcard);
1386 if (!NT_STATUS_IS_OK(nt_status)) {
1387 reply_nterror(req, nt_status);
1388 END_PROFILE(SMBsearch);
1392 nt_status = resolve_dfspath_wcard(ctx, conn,
1393 req->flags2 & FLAGS2_DFS_PATHNAMES,
1396 &mask_contains_wcard);
1397 if (!NT_STATUS_IS_OK(nt_status)) {
1398 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1399 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1400 ERRSRV, ERRbadpath);
1401 END_PROFILE(SMBsearch);
1404 reply_nterror(req, nt_status);
1405 END_PROFILE(SMBsearch);
1410 status_len = SVAL(p, 0);
1413 /* dirtype &= ~aDIR; */
1415 if (status_len == 0) {
1416 struct smb_filename *smb_fname = NULL;
1418 nt_status = unix_convert(ctx, conn, path, &smb_fname,
1419 UCF_ALLOW_WCARD_LCOMP);
1420 if (!NT_STATUS_IS_OK(nt_status)) {
1421 reply_nterror(req, nt_status);
1422 END_PROFILE(SMBsearch);
1426 nt_status = get_full_smb_filename(ctx, smb_fname, &directory);
1427 TALLOC_FREE(smb_fname);
1428 if (!NT_STATUS_IS_OK(nt_status)) {
1429 reply_nterror(req, nt_status);
1430 END_PROFILE(SMBsearch);
1434 nt_status = check_name(conn, directory);
1435 if (!NT_STATUS_IS_OK(nt_status)) {
1436 reply_nterror(req, nt_status);
1437 END_PROFILE(SMBsearch);
1441 p = strrchr_m(directory,'/');
1442 if ((p != NULL) && (*directory != '/')) {
1444 directory = talloc_strndup(ctx, directory,
1445 PTR_DIFF(p, directory));
1448 directory = talloc_strdup(ctx,".");
1452 reply_nterror(req, NT_STATUS_NO_MEMORY);
1453 END_PROFILE(SMBsearch);
1457 memset((char *)status,'\0',21);
1458 SCVAL(status,0,(dirtype & 0x1F));
1460 nt_status = dptr_create(conn,
1466 mask_contains_wcard,
1469 if (!NT_STATUS_IS_OK(nt_status)) {
1470 reply_nterror(req, nt_status);
1471 END_PROFILE(SMBsearch);
1474 dptr_num = dptr_dnum(conn->dirptr);
1478 memcpy(status,p,21);
1479 status_dirtype = CVAL(status,0) & 0x1F;
1480 if (status_dirtype != (dirtype & 0x1F)) {
1481 dirtype = status_dirtype;
1484 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1485 if (!conn->dirptr) {
1488 string_set(&conn->dirpath,dptr_path(dptr_num));
1489 mask = dptr_wcard(dptr_num);
1494 * For a 'continue' search we have no string. So
1495 * check from the initial saved string.
1497 mask_contains_wcard = ms_has_wild(mask);
1498 dirtype = dptr_attr(dptr_num);
1501 DEBUG(4,("dptr_num is %d\n",dptr_num));
1503 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1504 dptr_init_search_op(conn->dirptr);
1506 if ((dirtype&0x1F) == aVOLID) {
1507 char buf[DIR_STRUCT_SIZE];
1508 memcpy(buf,status,21);
1509 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1510 0,aVOLID,0,!allow_long_path_components)) {
1511 reply_nterror(req, NT_STATUS_NO_MEMORY);
1512 END_PROFILE(SMBsearch);
1515 dptr_fill(buf+12,dptr_num);
1516 if (dptr_zero(buf+12) && (status_len==0)) {
1521 if (message_push_blob(&req->outbuf,
1522 data_blob_const(buf, sizeof(buf)))
1524 reply_nterror(req, NT_STATUS_NO_MEMORY);
1525 END_PROFILE(SMBsearch);
1533 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1536 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1537 conn->dirpath,lp_dontdescend(SNUM(conn))));
1538 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1539 check_descend = True;
1542 for (i=numentries;(i<maxentries) && !finished;i++) {
1543 finished = !get_dir_entry(ctx,
1554 char buf[DIR_STRUCT_SIZE];
1555 memcpy(buf,status,21);
1556 if (!make_dir_struct(ctx,
1562 convert_timespec_to_time_t(date),
1563 !allow_long_path_components)) {
1564 reply_nterror(req, NT_STATUS_NO_MEMORY);
1565 END_PROFILE(SMBsearch);
1568 if (!dptr_fill(buf+12,dptr_num)) {
1571 if (message_push_blob(&req->outbuf,
1572 data_blob_const(buf, sizeof(buf)))
1574 reply_nterror(req, NT_STATUS_NO_MEMORY);
1575 END_PROFILE(SMBsearch);
1585 /* If we were called as SMBffirst with smb_search_id == NULL
1586 and no entries were found then return error and close dirptr
1589 if (numentries == 0) {
1590 dptr_close(&dptr_num);
1591 } else if(expect_close && status_len == 0) {
1592 /* Close the dptr - we know it's gone */
1593 dptr_close(&dptr_num);
1596 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1597 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1598 dptr_close(&dptr_num);
1601 if ((numentries == 0) && !mask_contains_wcard) {
1602 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1603 END_PROFILE(SMBsearch);
1607 SSVAL(req->outbuf,smb_vwv0,numentries);
1608 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1609 SCVAL(smb_buf(req->outbuf),0,5);
1610 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1612 /* The replies here are never long name. */
1613 SSVAL(req->outbuf, smb_flg2,
1614 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1615 if (!allow_long_path_components) {
1616 SSVAL(req->outbuf, smb_flg2,
1617 SVAL(req->outbuf, smb_flg2)
1618 & (~FLAGS2_LONG_PATH_COMPONENTS));
1621 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1622 SSVAL(req->outbuf, smb_flg2,
1623 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1626 directory = dptr_path(dptr_num);
1629 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1630 smb_fn_name(req->cmd),
1632 directory ? directory : "./",
1637 END_PROFILE(SMBsearch);
1641 /****************************************************************************
1642 Reply to a fclose (stop directory search).
1643 ****************************************************************************/
1645 void reply_fclose(struct smb_request *req)
1653 bool path_contains_wcard = False;
1654 TALLOC_CTX *ctx = talloc_tos();
1656 START_PROFILE(SMBfclose);
1658 if (lp_posix_pathnames()) {
1659 reply_unknown_new(req, req->cmd);
1660 END_PROFILE(SMBfclose);
1664 p = (const char *)req->buf + 1;
1665 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1666 &err, &path_contains_wcard);
1667 if (!NT_STATUS_IS_OK(err)) {
1668 reply_nterror(req, err);
1669 END_PROFILE(SMBfclose);
1673 status_len = SVAL(p,0);
1676 if (status_len == 0) {
1677 reply_doserror(req, ERRSRV, ERRsrverror);
1678 END_PROFILE(SMBfclose);
1682 memcpy(status,p,21);
1684 if(dptr_fetch(status+12,&dptr_num)) {
1685 /* Close the dptr - we know it's gone */
1686 dptr_close(&dptr_num);
1689 reply_outbuf(req, 1, 0);
1690 SSVAL(req->outbuf,smb_vwv0,0);
1692 DEBUG(3,("search close\n"));
1694 END_PROFILE(SMBfclose);
1698 /****************************************************************************
1700 ****************************************************************************/
1702 void reply_open(struct smb_request *req)
1704 connection_struct *conn = req->conn;
1710 SMB_STRUCT_STAT sbuf;
1717 uint32 create_disposition;
1718 uint32 create_options = 0;
1720 TALLOC_CTX *ctx = talloc_tos();
1722 START_PROFILE(SMBopen);
1724 SET_STAT_INVALID(sbuf);
1727 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1728 END_PROFILE(SMBopen);
1732 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1733 deny_mode = SVAL(req->vwv+0, 0);
1734 dos_attr = SVAL(req->vwv+1, 0);
1736 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1737 STR_TERMINATE, &status);
1738 if (!NT_STATUS_IS_OK(status)) {
1739 reply_nterror(req, status);
1740 END_PROFILE(SMBopen);
1744 if (!map_open_params_to_ntcreate(
1745 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1746 &share_mode, &create_disposition, &create_options)) {
1747 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1748 END_PROFILE(SMBopen);
1752 status = SMB_VFS_CREATE_FILE(
1755 0, /* root_dir_fid */
1757 CFF_DOS_PATH, /* create_file_flags */
1758 access_mask, /* access_mask */
1759 share_mode, /* share_access */
1760 create_disposition, /* create_disposition*/
1761 create_options, /* create_options */
1762 dos_attr, /* file_attributes */
1763 oplock_request, /* oplock_request */
1764 0, /* allocation_size */
1771 if (!NT_STATUS_IS_OK(status)) {
1772 if (open_was_deferred(req->mid)) {
1773 /* We have re-scheduled this call. */
1774 END_PROFILE(SMBopen);
1777 reply_openerror(req, status);
1778 END_PROFILE(SMBopen);
1782 size = sbuf.st_ex_size;
1783 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1784 mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime);
1787 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1788 close_file(req, fsp, ERROR_CLOSE);
1789 reply_doserror(req, ERRDOS,ERRnoaccess);
1790 END_PROFILE(SMBopen);
1794 reply_outbuf(req, 7, 0);
1795 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1796 SSVAL(req->outbuf,smb_vwv1,fattr);
1797 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1798 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1800 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1802 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1803 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1805 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1806 SCVAL(req->outbuf,smb_flg,
1807 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1810 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1811 SCVAL(req->outbuf,smb_flg,
1812 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1814 END_PROFILE(SMBopen);
1818 /****************************************************************************
1819 Reply to an open and X.
1820 ****************************************************************************/
1822 void reply_open_and_X(struct smb_request *req)
1824 connection_struct *conn = req->conn;
1829 /* Breakout the oplock request bits so we can set the
1830 reply bits separately. */
1831 int ex_oplock_request;
1832 int core_oplock_request;
1835 int smb_sattr = SVAL(req->vwv+4, 0);
1836 uint32 smb_time = make_unix_date3(req->vwv+6);
1841 SMB_STRUCT_STAT sbuf;
1845 uint64_t allocation_size;
1846 ssize_t retval = -1;
1849 uint32 create_disposition;
1850 uint32 create_options = 0;
1851 TALLOC_CTX *ctx = talloc_tos();
1853 START_PROFILE(SMBopenX);
1855 if (req->wct < 15) {
1856 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1857 END_PROFILE(SMBopenX);
1861 SET_STAT_INVALID(sbuf);
1863 open_flags = SVAL(req->vwv+2, 0);
1864 deny_mode = SVAL(req->vwv+3, 0);
1865 smb_attr = SVAL(req->vwv+5, 0);
1866 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1867 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1868 oplock_request = ex_oplock_request | core_oplock_request;
1869 smb_ofun = SVAL(req->vwv+8, 0);
1870 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1872 /* If it's an IPC, pass off the pipe handler. */
1874 if (lp_nt_pipe_support()) {
1875 reply_open_pipe_and_X(conn, req);
1877 reply_doserror(req, ERRSRV, ERRaccess);
1879 END_PROFILE(SMBopenX);
1883 /* XXXX we need to handle passed times, sattr and flags */
1884 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1885 STR_TERMINATE, &status);
1886 if (!NT_STATUS_IS_OK(status)) {
1887 reply_nterror(req, status);
1888 END_PROFILE(SMBopenX);
1892 if (!map_open_params_to_ntcreate(
1893 fname, deny_mode, smb_ofun, &access_mask,
1894 &share_mode, &create_disposition, &create_options)) {
1895 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1896 END_PROFILE(SMBopenX);
1900 status = SMB_VFS_CREATE_FILE(
1903 0, /* root_dir_fid */
1905 CFF_DOS_PATH, /* create_file_flags */
1906 access_mask, /* access_mask */
1907 share_mode, /* share_access */
1908 create_disposition, /* create_disposition*/
1909 create_options, /* create_options */
1910 smb_attr, /* file_attributes */
1911 oplock_request, /* oplock_request */
1912 0, /* allocation_size */
1916 &smb_action, /* pinfo */
1919 if (!NT_STATUS_IS_OK(status)) {
1920 END_PROFILE(SMBopenX);
1921 if (open_was_deferred(req->mid)) {
1922 /* We have re-scheduled this call. */
1925 reply_openerror(req, status);
1929 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1930 if the file is truncated or created. */
1931 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1932 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1933 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1934 close_file(req, fsp, ERROR_CLOSE);
1935 reply_nterror(req, NT_STATUS_DISK_FULL);
1936 END_PROFILE(SMBopenX);
1939 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1941 close_file(req, fsp, ERROR_CLOSE);
1942 reply_nterror(req, NT_STATUS_DISK_FULL);
1943 END_PROFILE(SMBopenX);
1946 sbuf.st_ex_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
1949 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1950 mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime);
1952 close_file(req, fsp, ERROR_CLOSE);
1953 reply_doserror(req, ERRDOS, ERRnoaccess);
1954 END_PROFILE(SMBopenX);
1958 /* If the caller set the extended oplock request bit
1959 and we granted one (by whatever means) - set the
1960 correct bit for extended oplock reply.
1963 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1964 smb_action |= EXTENDED_OPLOCK_GRANTED;
1967 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1968 smb_action |= EXTENDED_OPLOCK_GRANTED;
1971 /* If the caller set the core oplock request bit
1972 and we granted one (by whatever means) - set the
1973 correct bit for core oplock reply.
1976 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1977 reply_outbuf(req, 19, 0);
1979 reply_outbuf(req, 15, 0);
1982 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1983 SCVAL(req->outbuf, smb_flg,
1984 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1987 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1988 SCVAL(req->outbuf, smb_flg,
1989 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1992 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1993 SSVAL(req->outbuf,smb_vwv3,fattr);
1994 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1995 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1997 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1999 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_ex_size);
2000 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2001 SSVAL(req->outbuf,smb_vwv11,smb_action);
2003 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2004 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2007 END_PROFILE(SMBopenX);
2012 /****************************************************************************
2013 Reply to a SMBulogoffX.
2014 ****************************************************************************/
2016 void reply_ulogoffX(struct smb_request *req)
2018 struct smbd_server_connection *sconn = smbd_server_conn;
2021 START_PROFILE(SMBulogoffX);
2023 vuser = get_valid_user_struct(sconn, req->vuid);
2026 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2030 /* in user level security we are supposed to close any files
2031 open by this user */
2032 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2033 file_close_user(req->vuid);
2036 invalidate_vuid(sconn, req->vuid);
2038 reply_outbuf(req, 2, 0);
2040 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2042 END_PROFILE(SMBulogoffX);
2046 /****************************************************************************
2047 Reply to a mknew or a create.
2048 ****************************************************************************/
2050 void reply_mknew(struct smb_request *req)
2052 connection_struct *conn = req->conn;
2055 struct smb_file_time ft;
2057 int oplock_request = 0;
2058 SMB_STRUCT_STAT sbuf;
2060 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2061 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2062 uint32 create_disposition;
2063 uint32 create_options = 0;
2064 TALLOC_CTX *ctx = talloc_tos();
2066 START_PROFILE(SMBcreate);
2068 SET_STAT_INVALID(sbuf);
2071 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2072 END_PROFILE(SMBcreate);
2076 fattr = SVAL(req->vwv+0, 0);
2077 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2080 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2082 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2083 STR_TERMINATE, &status);
2084 if (!NT_STATUS_IS_OK(status)) {
2085 reply_nterror(req, status);
2086 END_PROFILE(SMBcreate);
2090 if (fattr & aVOLID) {
2091 DEBUG(0,("Attempt to create file (%s) with volid set - "
2092 "please report this\n", fname));
2095 if(req->cmd == SMBmknew) {
2096 /* We should fail if file exists. */
2097 create_disposition = FILE_CREATE;
2099 /* Create if file doesn't exist, truncate if it does. */
2100 create_disposition = FILE_OVERWRITE_IF;
2103 status = SMB_VFS_CREATE_FILE(
2106 0, /* root_dir_fid */
2108 CFF_DOS_PATH, /* create_file_flags */
2109 access_mask, /* access_mask */
2110 share_mode, /* share_access */
2111 create_disposition, /* create_disposition*/
2112 create_options, /* create_options */
2113 fattr, /* file_attributes */
2114 oplock_request, /* oplock_request */
2115 0, /* allocation_size */
2122 if (!NT_STATUS_IS_OK(status)) {
2123 END_PROFILE(SMBcreate);
2124 if (open_was_deferred(req->mid)) {
2125 /* We have re-scheduled this call. */
2128 reply_openerror(req, status);
2132 ft.atime = sbuf.st_ex_atime; /* atime. */
2133 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true);
2134 if (!NT_STATUS_IS_OK(status)) {
2135 END_PROFILE(SMBcreate);
2136 reply_openerror(req, status);
2140 reply_outbuf(req, 1, 0);
2141 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2143 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2144 SCVAL(req->outbuf,smb_flg,
2145 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2148 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2149 SCVAL(req->outbuf,smb_flg,
2150 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2153 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2154 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2155 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2157 END_PROFILE(SMBcreate);
2161 /****************************************************************************
2162 Reply to a create temporary file.
2163 ****************************************************************************/
2165 void reply_ctemp(struct smb_request *req)
2167 connection_struct *conn = req->conn;
2168 struct smb_filename *smb_fname = NULL;
2176 TALLOC_CTX *ctx = talloc_tos();
2178 START_PROFILE(SMBctemp);
2181 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2185 fattr = SVAL(req->vwv+0, 0);
2186 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2188 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2189 STR_TERMINATE, &status);
2190 if (!NT_STATUS_IS_OK(status)) {
2191 reply_nterror(req, status);
2195 fname = talloc_asprintf(ctx,
2199 fname = talloc_strdup(ctx, "TMXXXXXX");
2203 reply_nterror(req, NT_STATUS_NO_MEMORY);
2207 status = resolve_dfspath(ctx, conn,
2208 req->flags2 & FLAGS2_DFS_PATHNAMES,
2211 if (!NT_STATUS_IS_OK(status)) {
2212 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2213 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2214 ERRSRV, ERRbadpath);
2217 reply_nterror(req, status);
2221 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
2222 if (!NT_STATUS_IS_OK(status)) {
2223 reply_nterror(req, status);
2227 status = get_full_smb_filename(ctx, smb_fname, &fname);
2228 if (!NT_STATUS_IS_OK(status)) {
2229 reply_nterror(req, status);
2233 status = check_name(conn, fname);
2234 if (!NT_STATUS_IS_OK(status)) {
2235 reply_nterror(req, status);
2239 tmpfd = mkstemp(fname);
2241 reply_unixerror(req, ERRDOS, ERRnoaccess);
2245 SET_STAT_INVALID(smb_fname->st);
2246 SMB_VFS_STAT(conn, fname, &smb_fname->st);
2248 /* We should fail if file does not exist. */
2249 status = SMB_VFS_CREATE_FILE(
2252 0, /* root_dir_fid */
2254 0, /* create_file_flags */
2255 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2256 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2257 FILE_OPEN, /* create_disposition*/
2258 0, /* create_options */
2259 fattr, /* file_attributes */
2260 oplock_request, /* oplock_request */
2261 0, /* allocation_size */
2266 &smb_fname->st); /* psbuf */
2268 /* close fd from mkstemp() */
2271 if (!NT_STATUS_IS_OK(status)) {
2272 if (open_was_deferred(req->mid)) {
2273 /* We have re-scheduled this call. */
2276 reply_openerror(req, status);
2280 reply_outbuf(req, 1, 0);
2281 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2283 /* the returned filename is relative to the directory */
2284 s = strrchr_m(fsp->fsp_name, '/');
2292 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2293 thing in the byte section. JRA */
2294 SSVALS(p, 0, -1); /* what is this? not in spec */
2296 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2298 reply_nterror(req, NT_STATUS_NO_MEMORY);
2302 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2303 SCVAL(req->outbuf, smb_flg,
2304 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2307 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2308 SCVAL(req->outbuf, smb_flg,
2309 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2312 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2313 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2314 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2316 TALLOC_FREE(smb_fname);
2317 END_PROFILE(SMBctemp);
2321 /*******************************************************************
2322 Check if a user is allowed to rename a file.
2323 ********************************************************************/
2325 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2326 uint16 dirtype, SMB_STRUCT_STAT *pst)
2330 if (!CAN_WRITE(conn)) {
2331 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2334 fmode = dos_mode(conn, fsp->fsp_name, pst);
2335 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2336 return NT_STATUS_NO_SUCH_FILE;
2339 if (S_ISDIR(pst->st_ex_mode)) {
2340 if (fsp->posix_open) {
2341 return NT_STATUS_OK;
2344 /* If no pathnames are open below this
2345 directory, allow the rename. */
2347 if (file_find_subpath(fsp)) {
2348 return NT_STATUS_ACCESS_DENIED;
2350 return NT_STATUS_OK;
2353 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2354 return NT_STATUS_OK;
2357 return NT_STATUS_ACCESS_DENIED;
2360 /*******************************************************************
2361 * unlink a file with all relevant access checks
2362 *******************************************************************/
2364 static NTSTATUS do_unlink(connection_struct *conn,
2365 struct smb_request *req,
2369 SMB_STRUCT_STAT sbuf;
2372 uint32 dirtype_orig = dirtype;
2375 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2377 if (!CAN_WRITE(conn)) {
2378 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2381 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2382 return map_nt_error_from_unix(errno);
2385 fattr = dos_mode(conn,fname,&sbuf);
2387 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2388 dirtype = aDIR|aARCH|aRONLY;
2391 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2393 return NT_STATUS_NO_SUCH_FILE;
2396 if (!dir_check_ftype(conn, fattr, dirtype)) {
2398 return NT_STATUS_FILE_IS_A_DIRECTORY;
2400 return NT_STATUS_NO_SUCH_FILE;
2403 if (dirtype_orig & 0x8000) {
2404 /* These will never be set for POSIX. */
2405 return NT_STATUS_NO_SUCH_FILE;
2409 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2410 return NT_STATUS_FILE_IS_A_DIRECTORY;
2413 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2414 return NT_STATUS_NO_SUCH_FILE;
2417 if (dirtype & 0xFF00) {
2418 /* These will never be set for POSIX. */
2419 return NT_STATUS_NO_SUCH_FILE;
2424 return NT_STATUS_NO_SUCH_FILE;
2427 /* Can't delete a directory. */
2429 return NT_STATUS_FILE_IS_A_DIRECTORY;
2434 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2435 return NT_STATUS_OBJECT_NAME_INVALID;
2436 #endif /* JRATEST */
2438 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2440 On a Windows share, a file with read-only dosmode can be opened with
2441 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2442 fails with NT_STATUS_CANNOT_DELETE error.
2444 This semantic causes a problem that a user can not
2445 rename a file with read-only dosmode on a Samba share
2446 from a Windows command prompt (i.e. cmd.exe, but can rename
2447 from Windows Explorer).
2450 if (!lp_delete_readonly(SNUM(conn))) {
2451 if (fattr & aRONLY) {
2452 return NT_STATUS_CANNOT_DELETE;
2456 /* On open checks the open itself will check the share mode, so
2457 don't do it here as we'll get it wrong. */
2459 status = SMB_VFS_CREATE_FILE
2462 0, /* root_dir_fid */
2464 0, /* create_file_flags */
2465 DELETE_ACCESS, /* access_mask */
2466 FILE_SHARE_NONE, /* share_access */
2467 FILE_OPEN, /* create_disposition*/
2468 FILE_NON_DIRECTORY_FILE, /* create_options */
2469 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2470 0, /* oplock_request */
2471 0, /* allocation_size */
2478 if (!NT_STATUS_IS_OK(status)) {
2479 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2480 nt_errstr(status)));
2484 /* The set is across all open files on this dev/inode pair. */
2485 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2486 close_file(req, fsp, NORMAL_CLOSE);
2487 return NT_STATUS_ACCESS_DENIED;
2490 return close_file(req, fsp, NORMAL_CLOSE);
2493 /****************************************************************************
2494 The guts of the unlink command, split out so it may be called by the NT SMB
2496 ****************************************************************************/
2498 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2499 uint32 dirtype, const char *name_in, bool has_wild)
2501 struct smb_filename *smb_fname = NULL;
2502 const char *directory = NULL;
2507 NTSTATUS status = NT_STATUS_OK;
2509 TALLOC_CTX *ctx = talloc_tos();
2511 status = unix_convert(ctx, conn, name_in, &smb_fname,
2512 has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
2513 if (!NT_STATUS_IS_OK(status)) {
2517 status = get_full_smb_filename(ctx, smb_fname, &name);
2518 if (!NT_STATUS_IS_OK(status)) {
2519 TALLOC_FREE(smb_fname);
2523 p = strrchr_m(name,'/');
2525 directory = talloc_strdup(ctx, ".");
2527 TALLOC_FREE(smb_fname);
2528 return NT_STATUS_NO_MEMORY;
2538 * We should only check the mangled cache
2539 * here if unix_convert failed. This means
2540 * that the path in 'mask' doesn't exist
2541 * on the file system and so we need to look
2542 * for a possible mangle. This patch from
2543 * Tine Smukavec <valentin.smukavec@hermes.si>.
2546 if (!VALID_STAT(smb_fname->st) && mangle_is_mangled(mask,conn->params)) {
2547 char *new_mask = NULL;
2548 mangle_lookup_name_from_8_3(ctx,
2556 TALLOC_FREE(smb_fname);
2559 directory = talloc_asprintf(ctx,
2564 return NT_STATUS_NO_MEMORY;
2567 dirtype = FILE_ATTRIBUTE_NORMAL;
2570 status = check_name(conn, directory);
2571 if (!NT_STATUS_IS_OK(status)) {
2575 status = do_unlink(conn, req, directory, dirtype);
2576 if (!NT_STATUS_IS_OK(status)) {
2582 struct smb_Dir *dir_hnd = NULL;
2586 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2587 return NT_STATUS_OBJECT_NAME_INVALID;
2590 if (strequal(mask,"????????.???")) {
2595 status = check_name(conn, directory);
2596 if (!NT_STATUS_IS_OK(status)) {
2600 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2602 if (dir_hnd == NULL) {
2603 return map_nt_error_from_unix(errno);
2606 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2607 the pattern matches against the long name, otherwise the short name
2608 We don't implement this yet XXXX
2611 status = NT_STATUS_NO_SUCH_FILE;
2613 while ((dname = ReadDirName(dir_hnd, &offset, &st))) {
2616 if (!is_visible_file(conn, directory, dname, &st,
2622 /* Quick check for "." and ".." */
2623 if (ISDOT(dname) || ISDOTDOT(dname)) {
2627 if(!mask_match(dname, mask, conn->case_sensitive)) {
2631 fname = talloc_asprintf(ctx, "%s/%s",
2635 return NT_STATUS_NO_MEMORY;
2638 status = check_name(conn, fname);
2639 if (!NT_STATUS_IS_OK(status)) {
2640 TALLOC_FREE(dir_hnd);
2644 status = do_unlink(conn, req, fname, dirtype);
2645 if (!NT_STATUS_IS_OK(status)) {
2651 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2656 TALLOC_FREE(dir_hnd);
2659 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2660 status = map_nt_error_from_unix(errno);
2666 /****************************************************************************
2668 ****************************************************************************/
2670 void reply_unlink(struct smb_request *req)
2672 connection_struct *conn = req->conn;
2676 bool path_contains_wcard = False;
2677 TALLOC_CTX *ctx = talloc_tos();
2679 START_PROFILE(SMBunlink);
2682 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2683 END_PROFILE(SMBunlink);
2687 dirtype = SVAL(req->vwv+0, 0);
2689 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2690 STR_TERMINATE, &status,
2691 &path_contains_wcard);
2692 if (!NT_STATUS_IS_OK(status)) {
2693 reply_nterror(req, status);
2694 END_PROFILE(SMBunlink);
2698 status = resolve_dfspath_wcard(ctx, conn,
2699 req->flags2 & FLAGS2_DFS_PATHNAMES,
2702 &path_contains_wcard);
2703 if (!NT_STATUS_IS_OK(status)) {
2704 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2705 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2706 ERRSRV, ERRbadpath);
2707 END_PROFILE(SMBunlink);
2710 reply_nterror(req, status);
2711 END_PROFILE(SMBunlink);
2715 DEBUG(3,("reply_unlink : %s\n",name));
2717 status = unlink_internals(conn, req, dirtype, name,
2718 path_contains_wcard);
2719 if (!NT_STATUS_IS_OK(status)) {
2720 if (open_was_deferred(req->mid)) {
2721 /* We have re-scheduled this call. */
2722 END_PROFILE(SMBunlink);
2725 reply_nterror(req, status);
2726 END_PROFILE(SMBunlink);
2730 reply_outbuf(req, 0, 0);
2731 END_PROFILE(SMBunlink);
2736 /****************************************************************************
2738 ****************************************************************************/
2740 static void fail_readraw(void)
2742 const char *errstr = talloc_asprintf(talloc_tos(),
2743 "FAIL ! reply_readbraw: socket write fail (%s)",
2748 exit_server_cleanly(errstr);
2751 /****************************************************************************
2752 Fake (read/write) sendfile. Returns -1 on read or write fail.
2753 ****************************************************************************/
2755 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2759 size_t tosend = nread;
2766 bufsize = MIN(nread, 65536);
2768 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2772 while (tosend > 0) {
2776 if (tosend > bufsize) {
2781 ret = read_file(fsp,buf,startpos,cur_read);
2787 /* If we had a short read, fill with zeros. */
2788 if (ret < cur_read) {
2789 memset(buf + ret, '\0', cur_read - ret);
2792 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2797 startpos += cur_read;
2801 return (ssize_t)nread;
2804 #if defined(WITH_SENDFILE)
2805 /****************************************************************************
2806 Deal with the case of sendfile reading less bytes from the file than
2807 requested. Fill with zeros (all we can do).
2808 ****************************************************************************/
2810 static void sendfile_short_send(files_struct *fsp,
2815 #define SHORT_SEND_BUFSIZE 1024
2816 if (nread < headersize) {
2817 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2818 "header for file %s (%s). Terminating\n",
2819 fsp->fsp_name, strerror(errno) ));
2820 exit_server_cleanly("sendfile_short_send failed");
2823 nread -= headersize;
2825 if (nread < smb_maxcnt) {
2826 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2828 exit_server_cleanly("sendfile_short_send: "
2832 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2833 "with zeros !\n", fsp->fsp_name));
2835 while (nread < smb_maxcnt) {
2837 * We asked for the real file size and told sendfile
2838 * to not go beyond the end of the file. But it can
2839 * happen that in between our fstat call and the
2840 * sendfile call the file was truncated. This is very
2841 * bad because we have already announced the larger
2842 * number of bytes to the client.
2844 * The best we can do now is to send 0-bytes, just as
2845 * a read from a hole in a sparse file would do.
2847 * This should happen rarely enough that I don't care
2848 * about efficiency here :-)
2852 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2853 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2854 exit_server_cleanly("sendfile_short_send: "
2855 "write_data failed");
2862 #endif /* defined WITH_SENDFILE */
2864 /****************************************************************************
2865 Return a readbraw error (4 bytes of zero).
2866 ****************************************************************************/
2868 static void reply_readbraw_error(void)
2872 if (write_data(smbd_server_fd(),header,4) != 4) {
2877 /****************************************************************************
2878 Use sendfile in readbraw.
2879 ****************************************************************************/
2881 static void send_file_readbraw(connection_struct *conn,
2882 struct smb_request *req,
2888 char *outbuf = NULL;
2891 #if defined(WITH_SENDFILE)
2893 * We can only use sendfile on a non-chained packet
2894 * but we can use on a non-oplocked file. tridge proved this
2895 * on a train in Germany :-). JRA.
2896 * reply_readbraw has already checked the length.
2899 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2900 (fsp->wcp == NULL) &&
2901 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2902 ssize_t sendfile_read = -1;
2904 DATA_BLOB header_blob;
2906 _smb_setlen(header,nread);
2907 header_blob = data_blob_const(header, 4);
2909 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2910 &header_blob, startpos, nread)) == -1) {
2911 /* Returning ENOSYS means no data at all was sent.
2912 * Do this as a normal read. */
2913 if (errno == ENOSYS) {
2914 goto normal_readbraw;
2918 * Special hack for broken Linux with no working sendfile. If we
2919 * return EINTR we sent the header but not the rest of the data.
2920 * Fake this up by doing read/write calls.
2922 if (errno == EINTR) {
2923 /* Ensure we don't do this again. */
2924 set_use_sendfile(SNUM(conn), False);
2925 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2927 if (fake_sendfile(fsp, startpos, nread) == -1) {
2928 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2929 fsp->fsp_name, strerror(errno) ));
2930 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2935 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2936 fsp->fsp_name, strerror(errno) ));
2937 exit_server_cleanly("send_file_readbraw sendfile failed");
2938 } else if (sendfile_read == 0) {
2940 * Some sendfile implementations return 0 to indicate
2941 * that there was a short read, but nothing was
2942 * actually written to the socket. In this case,
2943 * fallback to the normal read path so the header gets
2944 * the correct byte count.
2946 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2947 "bytes falling back to the normal read: "
2948 "%s\n", fsp->fsp_name));
2949 goto normal_readbraw;
2952 /* Deal with possible short send. */
2953 if (sendfile_read != 4+nread) {
2954 sendfile_short_send(fsp, sendfile_read, 4, nread);
2962 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2964 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2965 (unsigned)(nread+4)));
2966 reply_readbraw_error();
2971 ret = read_file(fsp,outbuf+4,startpos,nread);
2972 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2981 _smb_setlen(outbuf,ret);
2982 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2985 TALLOC_FREE(outbuf);
2988 /****************************************************************************
2989 Reply to a readbraw (core+ protocol).
2990 ****************************************************************************/
2992 void reply_readbraw(struct smb_request *req)
2994 connection_struct *conn = req->conn;
2995 ssize_t maxcount,mincount;
2999 struct lock_struct lock;
3003 START_PROFILE(SMBreadbraw);
3005 if (srv_is_signing_active(smbd_server_conn) ||
3006 is_encrypted_packet(req->inbuf)) {
3007 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3008 "raw reads/writes are disallowed.");
3012 reply_readbraw_error();
3013 END_PROFILE(SMBreadbraw);
3018 * Special check if an oplock break has been issued
3019 * and the readraw request croses on the wire, we must
3020 * return a zero length response here.
3023 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3026 * We have to do a check_fsp by hand here, as
3027 * we must always return 4 zero bytes on error,
3031 if (!fsp || !conn || conn != fsp->conn ||
3032 req->vuid != fsp->vuid ||
3033 fsp->is_directory || fsp->fh->fd == -1) {
3035 * fsp could be NULL here so use the value from the packet. JRA.
3037 DEBUG(3,("reply_readbraw: fnum %d not valid "
3039 (int)SVAL(req->vwv+0, 0)));
3040 reply_readbraw_error();
3041 END_PROFILE(SMBreadbraw);
3045 /* Do a "by hand" version of CHECK_READ. */
3046 if (!(fsp->can_read ||
3047 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3048 (fsp->access_mask & FILE_EXECUTE)))) {
3049 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3050 (int)SVAL(req->vwv+0, 0)));
3051 reply_readbraw_error();
3052 END_PROFILE(SMBreadbraw);
3056 flush_write_cache(fsp, READRAW_FLUSH);
3058 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3059 if(req->wct == 10) {
3061 * This is a large offset (64 bit) read.
3063 #ifdef LARGE_SMB_OFF_T
3065 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3067 #else /* !LARGE_SMB_OFF_T */
3070 * Ensure we haven't been sent a >32 bit offset.
3073 if(IVAL(req->vwv+8, 0) != 0) {
3074 DEBUG(0,("reply_readbraw: large offset "
3075 "(%x << 32) used and we don't support "
3076 "64 bit offsets.\n",
3077 (unsigned int)IVAL(req->vwv+8, 0) ));
3078 reply_readbraw_error();
3079 END_PROFILE(SMBreadbraw);
3083 #endif /* LARGE_SMB_OFF_T */
3086 DEBUG(0,("reply_readbraw: negative 64 bit "
3087 "readraw offset (%.0f) !\n",
3088 (double)startpos ));
3089 reply_readbraw_error();
3090 END_PROFILE(SMBreadbraw);
3095 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3096 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3098 /* ensure we don't overrun the packet size */
3099 maxcount = MIN(65535,maxcount);
3101 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3102 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3105 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3106 reply_readbraw_error();
3107 END_PROFILE(SMBreadbraw);
3111 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3112 size = st.st_ex_size;
3115 if (startpos >= size) {
3118 nread = MIN(maxcount,(size - startpos));
3121 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3122 if (nread < mincount)
3126 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3127 "min=%lu nread=%lu\n",
3128 fsp->fnum, (double)startpos,
3129 (unsigned long)maxcount,
3130 (unsigned long)mincount,
3131 (unsigned long)nread ) );
3133 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3135 DEBUG(5,("reply_readbraw finished\n"));
3137 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3139 END_PROFILE(SMBreadbraw);
3144 #define DBGC_CLASS DBGC_LOCKING
3146 /****************************************************************************
3147 Reply to a lockread (core+ protocol).
3148 ****************************************************************************/
3150 void reply_lockread(struct smb_request *req)
3152 connection_struct *conn = req->conn;
3159 struct byte_range_lock *br_lck = NULL;
3161 struct smbd_server_connection *sconn = smbd_server_conn;
3163 START_PROFILE(SMBlockread);
3166 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3167 END_PROFILE(SMBlockread);
3171 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3173 if (!check_fsp(conn, req, fsp)) {
3174 END_PROFILE(SMBlockread);
3178 if (!CHECK_READ(fsp,req)) {
3179 reply_doserror(req, ERRDOS, ERRbadaccess);
3180 END_PROFILE(SMBlockread);
3184 numtoread = SVAL(req->vwv+1, 0);
3185 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3187 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3189 reply_outbuf(req, 5, numtoread + 3);
3191 data = smb_buf(req->outbuf) + 3;
3194 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3195 * protocol request that predates the read/write lock concept.
3196 * Thus instead of asking for a read lock here we need to ask
3197 * for a write lock. JRA.
3198 * Note that the requested lock size is unaffected by max_recv.
3201 br_lck = do_lock(smbd_messaging_context(),
3204 (uint64_t)numtoread,
3208 False, /* Non-blocking lock. */
3212 TALLOC_FREE(br_lck);
3214 if (NT_STATUS_V(status)) {
3215 reply_nterror(req, status);
3216 END_PROFILE(SMBlockread);
3221 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3224 if (numtoread > sconn->smb1.negprot.max_recv) {
3225 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3226 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3227 (unsigned int)numtoread,
3228 (unsigned int)sconn->smb1.negprot.max_recv));
3229 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3231 nread = read_file(fsp,data,startpos,numtoread);
3234 reply_unixerror(req, ERRDOS, ERRnoaccess);
3235 END_PROFILE(SMBlockread);
3239 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3241 SSVAL(req->outbuf,smb_vwv0,nread);
3242 SSVAL(req->outbuf,smb_vwv5,nread+3);
3243 p = smb_buf(req->outbuf);
3244 SCVAL(p,0,0); /* pad byte. */
3247 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3248 fsp->fnum, (int)numtoread, (int)nread));
3250 END_PROFILE(SMBlockread);
3255 #define DBGC_CLASS DBGC_ALL
3257 /****************************************************************************
3259 ****************************************************************************/
3261 void reply_read(struct smb_request *req)
3263 connection_struct *conn = req->conn;
3270 struct lock_struct lock;
3271 struct smbd_server_connection *sconn = smbd_server_conn;
3273 START_PROFILE(SMBread);
3276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3277 END_PROFILE(SMBread);
3281 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3283 if (!check_fsp(conn, req, fsp)) {
3284 END_PROFILE(SMBread);
3288 if (!CHECK_READ(fsp,req)) {
3289 reply_doserror(req, ERRDOS, ERRbadaccess);
3290 END_PROFILE(SMBread);
3294 numtoread = SVAL(req->vwv+1, 0);
3295 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3297 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3300 * The requested read size cannot be greater than max_recv. JRA.
3302 if (numtoread > sconn->smb1.negprot.max_recv) {
3303 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3304 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3305 (unsigned int)numtoread,
3306 (unsigned int)sconn->smb1.negprot.max_recv));
3307 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3310 reply_outbuf(req, 5, numtoread+3);
3312 data = smb_buf(req->outbuf) + 3;
3314 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3315 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3318 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3319 reply_doserror(req, ERRDOS,ERRlock);
3320 END_PROFILE(SMBread);
3325 nread = read_file(fsp,data,startpos,numtoread);
3328 reply_unixerror(req, ERRDOS,ERRnoaccess);
3332 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3334 SSVAL(req->outbuf,smb_vwv0,nread);
3335 SSVAL(req->outbuf,smb_vwv5,nread+3);
3336 SCVAL(smb_buf(req->outbuf),0,1);
3337 SSVAL(smb_buf(req->outbuf),1,nread);
3339 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3340 fsp->fnum, (int)numtoread, (int)nread ) );
3343 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3345 END_PROFILE(SMBread);
3349 /****************************************************************************
3351 ****************************************************************************/
3353 static int setup_readX_header(struct smb_request *req, char *outbuf,
3359 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3360 data = smb_buf(outbuf);
3362 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3364 SCVAL(outbuf,smb_vwv0,0xFF);
3365 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3366 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3367 SSVAL(outbuf,smb_vwv6,
3369 + 1 /* the wct field */
3370 + 12 * sizeof(uint16_t) /* vwv */
3371 + 2); /* the buflen field */
3372 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3373 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3374 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3375 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3379 /****************************************************************************
3380 Reply to a read and X - possibly using sendfile.
3381 ****************************************************************************/
3383 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3384 files_struct *fsp, SMB_OFF_T startpos,
3387 SMB_STRUCT_STAT sbuf;
3389 struct lock_struct lock;
3391 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3392 reply_unixerror(req, ERRDOS, ERRnoaccess);
3396 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3397 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3400 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3401 reply_doserror(req, ERRDOS, ERRlock);
3405 if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
3406 || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
3408 * We already know that we would do a short read, so don't
3409 * try the sendfile() path.
3411 goto nosendfile_read;
3414 #if defined(WITH_SENDFILE)
3416 * We can only use sendfile on a non-chained packet
3417 * but we can use on a non-oplocked file. tridge proved this
3418 * on a train in Germany :-). JRA.
3421 if (!req_is_in_chain(req) &&
3422 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3423 (fsp->wcp == NULL) &&
3424 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3425 uint8 headerbuf[smb_size + 12 * 2];
3429 * Set up the packet header before send. We
3430 * assume here the sendfile will work (get the
3431 * correct amount of data).
3434 header = data_blob_const(headerbuf, sizeof(headerbuf));
3436 construct_reply_common_req(req, (char *)headerbuf);
3437 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3439 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3440 /* Returning ENOSYS means no data at all was sent.
3441 Do this as a normal read. */
3442 if (errno == ENOSYS) {
3447 * Special hack for broken Linux with no working sendfile. If we
3448 * return EINTR we sent the header but not the rest of the data.
3449 * Fake this up by doing read/write calls.
3452 if (errno == EINTR) {
3453 /* Ensure we don't do this again. */
3454 set_use_sendfile(SNUM(conn), False);
3455 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3456 nread = fake_sendfile(fsp, startpos,
3459 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3460 fsp->fsp_name, strerror(errno) ));
3461 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3463 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3464 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3465 /* No outbuf here means successful sendfile. */
3469 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3470 fsp->fsp_name, strerror(errno) ));
3471 exit_server_cleanly("send_file_readX sendfile failed");
3472 } else if (nread == 0) {
3474 * Some sendfile implementations return 0 to indicate
3475 * that there was a short read, but nothing was
3476 * actually written to the socket. In this case,
3477 * fallback to the normal read path so the header gets
3478 * the correct byte count.
3480 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3481 "falling back to the normal read: %s\n",
3486 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3487 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3489 /* Deal with possible short send. */
3490 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3491 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3493 /* No outbuf here means successful sendfile. */
3494 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3495 SMB_PERFCOUNT_END(&req->pcd);
3503 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3504 uint8 headerbuf[smb_size + 2*12];
3506 construct_reply_common_req(req, (char *)headerbuf);
3507 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3509 /* Send out the header. */
3510 if (write_data(smbd_server_fd(), (char *)headerbuf,
3511 sizeof(headerbuf)) != sizeof(headerbuf)) {
3512 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3513 fsp->fsp_name, strerror(errno) ));
3514 exit_server_cleanly("send_file_readX sendfile failed");
3516 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3518 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3519 fsp->fsp_name, strerror(errno) ));
3520 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3527 reply_outbuf(req, 12, smb_maxcnt);
3529 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3531 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3534 reply_unixerror(req, ERRDOS, ERRnoaccess);
3538 setup_readX_header(req, (char *)req->outbuf, nread);
3540 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3541 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3547 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3548 TALLOC_FREE(req->outbuf);
3552 /****************************************************************************
3553 Reply to a read and X.
3554 ****************************************************************************/
3556 void reply_read_and_X(struct smb_request *req)
3558 connection_struct *conn = req->conn;
3562 bool big_readX = False;
3564 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3567 START_PROFILE(SMBreadX);
3569 if ((req->wct != 10) && (req->wct != 12)) {
3570 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3574 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3575 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3576 smb_maxcnt = SVAL(req->vwv+5, 0);
3578 /* If it's an IPC, pass off the pipe handler. */
3580 reply_pipe_read_and_X(req);
3581 END_PROFILE(SMBreadX);
3585 if (!check_fsp(conn, req, fsp)) {
3586 END_PROFILE(SMBreadX);
3590 if (!CHECK_READ(fsp,req)) {
3591 reply_doserror(req, ERRDOS,ERRbadaccess);
3592 END_PROFILE(SMBreadX);
3596 if (global_client_caps & CAP_LARGE_READX) {
3597 size_t upper_size = SVAL(req->vwv+7, 0);
3598 smb_maxcnt |= (upper_size<<16);
3599 if (upper_size > 1) {
3600 /* Can't do this on a chained packet. */
3601 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3602 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3603 END_PROFILE(SMBreadX);
3606 /* We currently don't do this on signed or sealed data. */
3607 if (srv_is_signing_active(smbd_server_conn) ||
3608 is_encrypted_packet(req->inbuf)) {
3609 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3610 END_PROFILE(SMBreadX);
3613 /* Is there room in the reply for this data ? */
3614 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3616 NT_STATUS_INVALID_PARAMETER);
3617 END_PROFILE(SMBreadX);
3624 if (req->wct == 12) {
3625 #ifdef LARGE_SMB_OFF_T
3627 * This is a large offset (64 bit) read.
3629 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3631 #else /* !LARGE_SMB_OFF_T */
3634 * Ensure we haven't been sent a >32 bit offset.
3637 if(IVAL(req->vwv+10, 0) != 0) {
3638 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3639 "used and we don't support 64 bit offsets.\n",
3640 (unsigned int)IVAL(req->vwv+10, 0) ));
3641 END_PROFILE(SMBreadX);
3642 reply_doserror(req, ERRDOS, ERRbadaccess);
3646 #endif /* LARGE_SMB_OFF_T */
3651 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3655 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3658 END_PROFILE(SMBreadX);
3662 /****************************************************************************
3663 Error replies to writebraw must have smb_wct == 1. Fix this up.
3664 ****************************************************************************/
3666 void error_to_writebrawerr(struct smb_request *req)
3668 uint8 *old_outbuf = req->outbuf;
3670 reply_outbuf(req, 1, 0);
3672 memcpy(req->outbuf, old_outbuf, smb_size);
3673 TALLOC_FREE(old_outbuf);
3676 /****************************************************************************
3677 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3678 ****************************************************************************/
3680 void reply_writebraw(struct smb_request *req)
3682 connection_struct *conn = req->conn;
3685 ssize_t total_written=0;
3686 size_t numtowrite=0;
3692 struct lock_struct lock;
3695 START_PROFILE(SMBwritebraw);
3698 * If we ever reply with an error, it must have the SMB command
3699 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3702 SCVAL(req->inbuf,smb_com,SMBwritec);
3704 if (srv_is_signing_active(smbd_server_conn)) {
3705 END_PROFILE(SMBwritebraw);
3706 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3707 "raw reads/writes are disallowed.");
3710 if (req->wct < 12) {
3711 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3712 error_to_writebrawerr(req);
3713 END_PROFILE(SMBwritebraw);
3717 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3718 if (!check_fsp(conn, req, fsp)) {
3719 error_to_writebrawerr(req);
3720 END_PROFILE(SMBwritebraw);
3724 if (!CHECK_WRITE(fsp)) {
3725 reply_doserror(req, ERRDOS, ERRbadaccess);
3726 error_to_writebrawerr(req);
3727 END_PROFILE(SMBwritebraw);
3731 tcount = IVAL(req->vwv+1, 0);
3732 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3733 write_through = BITSETW(req->vwv+7,0);
3735 /* We have to deal with slightly different formats depending
3736 on whether we are using the core+ or lanman1.0 protocol */
3738 if(Protocol <= PROTOCOL_COREPLUS) {
3739 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3740 data = smb_buf(req->inbuf);
3742 numtowrite = SVAL(req->vwv+10, 0);
3743 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3746 /* Ensure we don't write bytes past the end of this packet. */
3747 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3748 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3749 error_to_writebrawerr(req);
3750 END_PROFILE(SMBwritebraw);
3754 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3755 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3758 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3759 reply_doserror(req, ERRDOS, ERRlock);
3760 error_to_writebrawerr(req);
3761 END_PROFILE(SMBwritebraw);
3766 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3769 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3770 "wrote=%d sync=%d\n",
3771 fsp->fnum, (double)startpos, (int)numtowrite,
3772 (int)nwritten, (int)write_through));
3774 if (nwritten < (ssize_t)numtowrite) {
3775 reply_unixerror(req, ERRHRD, ERRdiskfull);
3776 error_to_writebrawerr(req);
3780 total_written = nwritten;
3782 /* Allocate a buffer of 64k + length. */
3783 buf = TALLOC_ARRAY(NULL, char, 65540);
3785 reply_doserror(req, ERRDOS, ERRnomem);
3786 error_to_writebrawerr(req);
3790 /* Return a SMBwritebraw message to the redirector to tell
3791 * it to send more bytes */
3793 memcpy(buf, req->inbuf, smb_size);
3794 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3795 SCVAL(buf,smb_com,SMBwritebraw);
3796 SSVALS(buf,smb_vwv0,0xFFFF);
3798 if (!srv_send_smb(smbd_server_fd(),
3800 false, 0, /* no signing */
3801 IS_CONN_ENCRYPTED(conn),
3803 exit_server_cleanly("reply_writebraw: srv_send_smb "
3807 /* Now read the raw data into the buffer and write it */
3808 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3810 if (!NT_STATUS_IS_OK(status)) {
3811 exit_server_cleanly("secondary writebraw failed");
3814 /* Set up outbuf to return the correct size */
3815 reply_outbuf(req, 1, 0);
3817 if (numtowrite != 0) {
3819 if (numtowrite > 0xFFFF) {
3820 DEBUG(0,("reply_writebraw: Oversize secondary write "
3821 "raw requested (%u). Terminating\n",
3822 (unsigned int)numtowrite ));
3823 exit_server_cleanly("secondary writebraw failed");
3826 if (tcount > nwritten+numtowrite) {
3827 DEBUG(3,("reply_writebraw: Client overestimated the "
3829 (int)tcount,(int)nwritten,(int)numtowrite));
3832 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3834 if (!NT_STATUS_IS_OK(status)) {
3835 DEBUG(0,("reply_writebraw: Oversize secondary write "
3836 "raw read failed (%s). Terminating\n",
3837 nt_errstr(status)));
3838 exit_server_cleanly("secondary writebraw failed");
3841 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3842 if (nwritten == -1) {
3844 reply_unixerror(req, ERRHRD, ERRdiskfull);
3845 error_to_writebrawerr(req);
3849 if (nwritten < (ssize_t)numtowrite) {
3850 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3851 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3855 total_written += nwritten;
3860 SSVAL(req->outbuf,smb_vwv0,total_written);
3862 status = sync_file(conn, fsp, write_through);
3863 if (!NT_STATUS_IS_OK(status)) {
3864 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3865 fsp->fsp_name, nt_errstr(status) ));
3866 reply_nterror(req, status);
3867 error_to_writebrawerr(req);
3871 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3873 fsp->fnum, (double)startpos, (int)numtowrite,
3874 (int)total_written));
3876 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3878 /* We won't return a status if write through is not selected - this
3879 * follows what WfWg does */
3880 END_PROFILE(SMBwritebraw);
3882 if (!write_through && total_written==tcount) {
3884 #if RABBIT_PELLET_FIX
3886 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3887 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3890 if (!send_keepalive(smbd_server_fd())) {
3891 exit_server_cleanly("reply_writebraw: send of "
3892 "keepalive failed");
3895 TALLOC_FREE(req->outbuf);
3900 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3902 END_PROFILE(SMBwritebraw);
3907 #define DBGC_CLASS DBGC_LOCKING
3909 /****************************************************************************
3910 Reply to a writeunlock (core+).
3911 ****************************************************************************/
3913 void reply_writeunlock(struct smb_request *req)
3915 connection_struct *conn = req->conn;
3916 ssize_t nwritten = -1;
3920 NTSTATUS status = NT_STATUS_OK;
3922 struct lock_struct lock;
3924 START_PROFILE(SMBwriteunlock);
3927 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3928 END_PROFILE(SMBwriteunlock);
3932 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3934 if (!check_fsp(conn, req, fsp)) {
3935 END_PROFILE(SMBwriteunlock);
3939 if (!CHECK_WRITE(fsp)) {
3940 reply_doserror(req, ERRDOS,ERRbadaccess);
3941 END_PROFILE(SMBwriteunlock);
3945 numtowrite = SVAL(req->vwv+1, 0);
3946 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3947 data = (const char *)req->buf + 3;
3950 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3951 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3954 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3955 reply_doserror(req, ERRDOS, ERRlock);
3956 END_PROFILE(SMBwriteunlock);
3961 /* The special X/Open SMB protocol handling of
3962 zero length writes is *NOT* done for
3964 if(numtowrite == 0) {
3967 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3970 status = sync_file(conn, fsp, False /* write through */);
3971 if (!NT_STATUS_IS_OK(status)) {
3972 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3973 fsp->fsp_name, nt_errstr(status) ));
3974 reply_nterror(req, status);
3978 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3979 reply_unixerror(req, ERRHRD, ERRdiskfull);
3984 status = do_unlock(smbd_messaging_context(),
3987 (uint64_t)numtowrite,
3991 if (NT_STATUS_V(status)) {
3992 reply_nterror(req, status);
3997 reply_outbuf(req, 1, 0);
3999 SSVAL(req->outbuf,smb_vwv0,nwritten);
4001 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4002 fsp->fnum, (int)numtowrite, (int)nwritten));
4006 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4009 END_PROFILE(SMBwriteunlock);
4014 #define DBGC_CLASS DBGC_ALL
4016 /****************************************************************************
4018 ****************************************************************************/
4020 void reply_write(struct smb_request *req)
4022 connection_struct *conn = req->conn;
4024 ssize_t nwritten = -1;
4028 struct lock_struct lock;
4031 START_PROFILE(SMBwrite);
4034 END_PROFILE(SMBwrite);
4035 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4039 /* If it's an IPC, pass off the pipe handler. */
4041 reply_pipe_write(req);
4042 END_PROFILE(SMBwrite);
4046 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4048 if (!check_fsp(conn, req, fsp)) {
4049 END_PROFILE(SMBwrite);
4053 if (!CHECK_WRITE(fsp)) {
4054 reply_doserror(req, ERRDOS, ERRbadaccess);
4055 END_PROFILE(SMBwrite);
4059 numtowrite = SVAL(req->vwv+1, 0);
4060 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4061 data = (const char *)req->buf + 3;
4063 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4064 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4067 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4068 reply_doserror(req, ERRDOS, ERRlock);
4069 END_PROFILE(SMBwrite);
4074 * X/Open SMB protocol says that if smb_vwv1 is
4075 * zero then the file size should be extended or
4076 * truncated to the size given in smb_vwv[2-3].
4079 if(numtowrite == 0) {
4081 * This is actually an allocate call, and set EOF. JRA.
4083 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4085 reply_nterror(req, NT_STATUS_DISK_FULL);
4088 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4090 reply_nterror(req, NT_STATUS_DISK_FULL);
4093 trigger_write_time_update_immediate(fsp);
4095 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4098 status = sync_file(conn, fsp, False);
4099 if (!NT_STATUS_IS_OK(status)) {
4100 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4101 fsp->fsp_name, nt_errstr(status) ));
4102 reply_nterror(req, status);
4106 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4107 reply_unixerror(req, ERRHRD, ERRdiskfull);
4111 reply_outbuf(req, 1, 0);
4113 SSVAL(req->outbuf,smb_vwv0,nwritten);
4115 if (nwritten < (ssize_t)numtowrite) {
4116 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4117 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4120 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4123 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4125 END_PROFILE(SMBwrite);
4129 /****************************************************************************
4130 Ensure a buffer is a valid writeX for recvfile purposes.
4131 ****************************************************************************/
4133 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4134 (2*14) + /* word count (including bcc) */ \
4137 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4140 connection_struct *conn = NULL;
4141 unsigned int doff = 0;
4142 size_t len = smb_len_large(inbuf);
4144 if (is_encrypted_packet(inbuf)) {
4145 /* Can't do this on encrypted
4150 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4154 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4155 CVAL(inbuf,smb_wct) != 14) {
4156 DEBUG(10,("is_valid_writeX_buffer: chained or "
4157 "invalid word length.\n"));
4161 conn = conn_find(SVAL(inbuf, smb_tid));
4163 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4167 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4170 if (IS_PRINT(conn)) {
4171 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4174 doff = SVAL(inbuf,smb_vwv11);
4176 numtowrite = SVAL(inbuf,smb_vwv10);
4178 if (len > doff && len - doff > 0xFFFF) {
4179 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4182 if (numtowrite == 0) {
4183 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4187 /* Ensure the sizes match up. */
4188 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4189 /* no pad byte...old smbclient :-( */
4190 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4192 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4196 if (len - doff != numtowrite) {
4197 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4198 "len = %u, doff = %u, numtowrite = %u\n",
4201 (unsigned int)numtowrite ));
4205 DEBUG(10,("is_valid_writeX_buffer: true "
4206 "len = %u, doff = %u, numtowrite = %u\n",
4209 (unsigned int)numtowrite ));
4214 /****************************************************************************
4215 Reply to a write and X.
4216 ****************************************************************************/
4218 void reply_write_and_X(struct smb_request *req)
4220 connection_struct *conn = req->conn;
4222 struct lock_struct lock;
4227 unsigned int smb_doff;
4228 unsigned int smblen;
4232 START_PROFILE(SMBwriteX);
4234 if ((req->wct != 12) && (req->wct != 14)) {
4235 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4236 END_PROFILE(SMBwriteX);
4240 numtowrite = SVAL(req->vwv+10, 0);
4241 smb_doff = SVAL(req->vwv+11, 0);
4242 smblen = smb_len(req->inbuf);
4244 if (req->unread_bytes > 0xFFFF ||
4245 (smblen > smb_doff &&
4246 smblen - smb_doff > 0xFFFF)) {
4247 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4250 if (req->unread_bytes) {
4251 /* Can't do a recvfile write on IPC$ */
4253 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4254 END_PROFILE(SMBwriteX);
4257 if (numtowrite != req->unread_bytes) {
4258 reply_doserror(req, ERRDOS, ERRbadmem);
4259 END_PROFILE(SMBwriteX);
4263 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4264 smb_doff + numtowrite > smblen) {
4265 reply_doserror(req, ERRDOS, ERRbadmem);
4266 END_PROFILE(SMBwriteX);
4271 /* If it's an IPC, pass off the pipe handler. */
4273 if (req->unread_bytes) {
4274 reply_doserror(req, ERRDOS, ERRbadmem);
4275 END_PROFILE(SMBwriteX);
4278 reply_pipe_write_and_X(req);
4279 END_PROFILE(SMBwriteX);
4283 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4284 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4285 write_through = BITSETW(req->vwv+7,0);
4287 if (!check_fsp(conn, req, fsp)) {
4288 END_PROFILE(SMBwriteX);
4292 if (!CHECK_WRITE(fsp)) {
4293 reply_doserror(req, ERRDOS, ERRbadaccess);
4294 END_PROFILE(SMBwriteX);
4298 data = smb_base(req->inbuf) + smb_doff;
4300 if(req->wct == 14) {
4301 #ifdef LARGE_SMB_OFF_T
4303 * This is a large offset (64 bit) write.
4305 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4307 #else /* !LARGE_SMB_OFF_T */
4310 * Ensure we haven't been sent a >32 bit offset.
4313 if(IVAL(req->vwv+12, 0) != 0) {
4314 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4315 "used and we don't support 64 bit offsets.\n",
4316 (unsigned int)IVAL(req->vwv+12, 0) ));
4317 reply_doserror(req, ERRDOS, ERRbadaccess);
4318 END_PROFILE(SMBwriteX);
4322 #endif /* LARGE_SMB_OFF_T */
4325 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4326 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4329 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4330 reply_doserror(req, ERRDOS, ERRlock);
4331 END_PROFILE(SMBwriteX);
4335 /* X/Open SMB protocol says that, unlike SMBwrite
4336 if the length is zero then NO truncation is
4337 done, just a write of zero. To truncate a file,
4340 if(numtowrite == 0) {
4344 if ((req->unread_bytes == 0) &&
4345 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4350 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4353 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4354 reply_unixerror(req, ERRHRD, ERRdiskfull);
4358 reply_outbuf(req, 6, 0);
4359 SSVAL(req->outbuf,smb_vwv2,nwritten);
4360 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4362 if (nwritten < (ssize_t)numtowrite) {
4363 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4364 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4367 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4368 fsp->fnum, (int)numtowrite, (int)nwritten));
4370 status = sync_file(conn, fsp, write_through);
4371 if (!NT_STATUS_IS_OK(status)) {
4372 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4373 fsp->fsp_name, nt_errstr(status) ));
4374 reply_nterror(req, status);
4378 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4380 END_PROFILE(SMBwriteX);
4385 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4387 END_PROFILE(SMBwriteX);
4391 /****************************************************************************
4393 ****************************************************************************/
4395 void reply_lseek(struct smb_request *req)
4397 connection_struct *conn = req->conn;
4403 START_PROFILE(SMBlseek);
4406 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4407 END_PROFILE(SMBlseek);
4411 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4413 if (!check_fsp(conn, req, fsp)) {
4417 flush_write_cache(fsp, SEEK_FLUSH);
4419 mode = SVAL(req->vwv+1, 0) & 3;
4420 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4421 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4430 res = fsp->fh->pos + startpos;
4441 if (umode == SEEK_END) {
4442 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4443 if(errno == EINVAL) {
4444 SMB_OFF_T current_pos = startpos;
4445 SMB_STRUCT_STAT sbuf;
4447 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4448 reply_unixerror(req, ERRDOS,
4450 END_PROFILE(SMBlseek);
4454 current_pos += sbuf.st_ex_size;
4456 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4461 reply_unixerror(req, ERRDOS, ERRnoaccess);
4462 END_PROFILE(SMBlseek);
4469 reply_outbuf(req, 2, 0);
4470 SIVAL(req->outbuf,smb_vwv0,res);
4472 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4473 fsp->fnum, (double)startpos, (double)res, mode));
4475 END_PROFILE(SMBlseek);
4479 /****************************************************************************
4481 ****************************************************************************/
4483 void reply_flush(struct smb_request *req)
4485 connection_struct *conn = req->conn;
4489 START_PROFILE(SMBflush);
4492 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4496 fnum = SVAL(req->vwv+0, 0);
4497 fsp = file_fsp(req, fnum);
4499 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4504 file_sync_all(conn);
4506 NTSTATUS status = sync_file(conn, fsp, True);
4507 if (!NT_STATUS_IS_OK(status)) {
4508 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4509 fsp->fsp_name, nt_errstr(status) ));
4510 reply_nterror(req, status);
4511 END_PROFILE(SMBflush);
4516 reply_outbuf(req, 0, 0);
4518 DEBUG(3,("flush\n"));
4519 END_PROFILE(SMBflush);
4523 /****************************************************************************
4525 conn POINTER CAN BE NULL HERE !
4526 ****************************************************************************/
4528 void reply_exit(struct smb_request *req)
4530 START_PROFILE(SMBexit);
4532 file_close_pid(req->smbpid, req->vuid);
4534 reply_outbuf(req, 0, 0);
4536 DEBUG(3,("exit\n"));
4538 END_PROFILE(SMBexit);
4542 /****************************************************************************
4543 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4544 ****************************************************************************/
4546 void reply_close(struct smb_request *req)
4548 connection_struct *conn = req->conn;
4549 NTSTATUS status = NT_STATUS_OK;
4550 files_struct *fsp = NULL;
4551 START_PROFILE(SMBclose);
4554 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4555 END_PROFILE(SMBclose);
4559 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4562 * We can only use check_fsp if we know it's not a directory.
4565 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4566 reply_doserror(req, ERRDOS, ERRbadfid);
4567 END_PROFILE(SMBclose);
4571 if(fsp->is_directory) {
4573 * Special case - close NT SMB directory handle.
4575 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4576 status = close_file(req, fsp, NORMAL_CLOSE);
4580 * Close ordinary file.
4583 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4584 fsp->fh->fd, fsp->fnum,
4585 conn->num_files_open));
4588 * Take care of any time sent in the close.
4591 t = srv_make_unix_date3(req->vwv+1);
4592 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4595 * close_file() returns the unix errno if an error
4596 * was detected on close - normally this is due to
4597 * a disk full error. If not then it was probably an I/O error.
4600 status = close_file(req, fsp, NORMAL_CLOSE);
4603 if (!NT_STATUS_IS_OK(status)) {
4604 reply_nterror(req, status);
4605 END_PROFILE(SMBclose);
4609 reply_outbuf(req, 0, 0);
4610 END_PROFILE(SMBclose);
4614 /****************************************************************************
4615 Reply to a writeclose (Core+ protocol).
4616 ****************************************************************************/
4618 void reply_writeclose(struct smb_request *req)
4620 connection_struct *conn = req->conn;
4622 ssize_t nwritten = -1;
4623 NTSTATUS close_status = NT_STATUS_OK;
4626 struct timespec mtime;
4628 struct lock_struct lock;
4630 START_PROFILE(SMBwriteclose);
4633 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4634 END_PROFILE(SMBwriteclose);
4638 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4640 if (!check_fsp(conn, req, fsp)) {
4641 END_PROFILE(SMBwriteclose);
4644 if (!CHECK_WRITE(fsp)) {
4645 reply_doserror(req, ERRDOS,ERRbadaccess);
4646 END_PROFILE(SMBwriteclose);
4650 numtowrite = SVAL(req->vwv+1, 0);
4651 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4652 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4653 data = (const char *)req->buf + 1;
4656 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4657 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4660 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4661 reply_doserror(req, ERRDOS,ERRlock);
4662 END_PROFILE(SMBwriteclose);
4667 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4669 set_close_write_time(fsp, mtime);
4672 * More insanity. W2K only closes the file if writelen > 0.
4677 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4679 close_status = close_file(req, fsp, NORMAL_CLOSE);
4682 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4683 fsp->fnum, (int)numtowrite, (int)nwritten,
4684 conn->num_files_open));
4686 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4687 reply_doserror(req, ERRHRD, ERRdiskfull);
4691 if(!NT_STATUS_IS_OK(close_status)) {
4692 reply_nterror(req, close_status);
4696 reply_outbuf(req, 1, 0);
4698 SSVAL(req->outbuf,smb_vwv0,nwritten);
4702 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4705 END_PROFILE(SMBwriteclose);
4710 #define DBGC_CLASS DBGC_LOCKING
4712 /****************************************************************************
4714 ****************************************************************************/
4716 void reply_lock(struct smb_request *req)
4718 connection_struct *conn = req->conn;
4719 uint64_t count,offset;
4722 struct byte_range_lock *br_lck = NULL;
4724 START_PROFILE(SMBlock);
4727 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4728 END_PROFILE(SMBlock);
4732 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4734 if (!check_fsp(conn, req, fsp)) {
4735 END_PROFILE(SMBlock);
4739 count = (uint64_t)IVAL(req->vwv+1, 0);
4740 offset = (uint64_t)IVAL(req->vwv+3, 0);
4742 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4743 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4745 br_lck = do_lock(smbd_messaging_context(),
4752 False, /* Non-blocking lock. */
4757 TALLOC_FREE(br_lck);
4759 if (NT_STATUS_V(status)) {
4760 reply_nterror(req, status);
4761 END_PROFILE(SMBlock);
4765 reply_outbuf(req, 0, 0);
4767 END_PROFILE(SMBlock);
4771 /****************************************************************************
4773 ****************************************************************************/
4775 void reply_unlock(struct smb_request *req)
4777 connection_struct *conn = req->conn;
4778 uint64_t count,offset;
4782 START_PROFILE(SMBunlock);
4785 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4786 END_PROFILE(SMBunlock);
4790 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4792 if (!check_fsp(conn, req, fsp)) {
4793 END_PROFILE(SMBunlock);
4797 count = (uint64_t)IVAL(req->vwv+1, 0);
4798 offset = (uint64_t)IVAL(req->vwv+3, 0);
4800 status = do_unlock(smbd_messaging_context(),
4807 if (NT_STATUS_V(status)) {
4808 reply_nterror(req, status);
4809 END_PROFILE(SMBunlock);
4813 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4814 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4816 reply_outbuf(req, 0, 0);
4818 END_PROFILE(SMBunlock);
4823 #define DBGC_CLASS DBGC_ALL
4825 /****************************************************************************
4827 conn POINTER CAN BE NULL HERE !
4828 ****************************************************************************/
4830 void reply_tdis(struct smb_request *req)
4832 connection_struct *conn = req->conn;
4833 START_PROFILE(SMBtdis);
4836 DEBUG(4,("Invalid connection in tdis\n"));
4837 reply_doserror(req, ERRSRV, ERRinvnid);
4838 END_PROFILE(SMBtdis);
4844 close_cnum(conn,req->vuid);
4847 reply_outbuf(req, 0, 0);
4848 END_PROFILE(SMBtdis);
4852 /****************************************************************************
4854 conn POINTER CAN BE NULL HERE !
4855 ****************************************************************************/
4857 void reply_echo(struct smb_request *req)
4859 connection_struct *conn = req->conn;
4860 struct smb_perfcount_data local_pcd;
4861 struct smb_perfcount_data *cur_pcd;
4865 START_PROFILE(SMBecho);
4867 smb_init_perfcount_data(&local_pcd);
4870 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4871 END_PROFILE(SMBecho);
4875 smb_reverb = SVAL(req->vwv+0, 0);
4877 reply_outbuf(req, 1, req->buflen);
4879 /* copy any incoming data back out */
4880 if (req->buflen > 0) {
4881 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4884 if (smb_reverb > 100) {
4885 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4889 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4891 /* this makes sure we catch the request pcd */
4892 if (seq_num == smb_reverb) {
4893 cur_pcd = &req->pcd;
4895 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4896 cur_pcd = &local_pcd;
4899 SSVAL(req->outbuf,smb_vwv0,seq_num);
4901 show_msg((char *)req->outbuf);
4902 if (!srv_send_smb(smbd_server_fd(),
4903 (char *)req->outbuf,
4904 true, req->seqnum+1,
4905 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4907 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4910 DEBUG(3,("echo %d times\n", smb_reverb));
4912 TALLOC_FREE(req->outbuf);
4914 END_PROFILE(SMBecho);
4918 /****************************************************************************
4919 Reply to a printopen.
4920 ****************************************************************************/
4922 void reply_printopen(struct smb_request *req)
4924 connection_struct *conn = req->conn;
4926 SMB_STRUCT_STAT sbuf;
4929 START_PROFILE(SMBsplopen);
4932 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4933 END_PROFILE(SMBsplopen);
4937 if (!CAN_PRINT(conn)) {
4938 reply_doserror(req, ERRDOS, ERRnoaccess);
4939 END_PROFILE(SMBsplopen);
4943 status = file_new(req, conn, &fsp);
4944 if(!NT_STATUS_IS_OK(status)) {
4945 reply_nterror(req, status);
4946 END_PROFILE(SMBsplopen);
4950 /* Open for exclusive use, write only. */
4951 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4953 if (!NT_STATUS_IS_OK(status)) {
4954 reply_nterror(req, status);
4955 END_PROFILE(SMBsplopen);
4959 reply_outbuf(req, 1, 0);
4960 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4962 DEBUG(3,("openprint fd=%d fnum=%d\n",
4963 fsp->fh->fd, fsp->fnum));
4965 END_PROFILE(SMBsplopen);
4969 /****************************************************************************
4970 Reply to a printclose.
4971 ****************************************************************************/
4973 void reply_printclose(struct smb_request *req)
4975 connection_struct *conn = req->conn;
4979 START_PROFILE(SMBsplclose);
4982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4983 END_PROFILE(SMBsplclose);
4987 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4989 if (!check_fsp(conn, req, fsp)) {
4990 END_PROFILE(SMBsplclose);
4994 if (!CAN_PRINT(conn)) {
4995 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4996 END_PROFILE(SMBsplclose);
5000 DEBUG(3,("printclose fd=%d fnum=%d\n",
5001 fsp->fh->fd,fsp->fnum));
5003 status = close_file(req, fsp, NORMAL_CLOSE);
5005 if(!NT_STATUS_IS_OK(status)) {
5006 reply_nterror(req, status);
5007 END_PROFILE(SMBsplclose);
5011 reply_outbuf(req, 0, 0);
5013 END_PROFILE(SMBsplclose);
5017 /****************************************************************************
5018 Reply to a printqueue.
5019 ****************************************************************************/
5021 void reply_printqueue(struct smb_request *req)
5023 connection_struct *conn = req->conn;
5027 START_PROFILE(SMBsplretq);
5030 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5031 END_PROFILE(SMBsplretq);
5035 max_count = SVAL(req->vwv+0, 0);
5036 start_index = SVAL(req->vwv+1, 0);
5038 /* we used to allow the client to get the cnum wrong, but that
5039 is really quite gross and only worked when there was only
5040 one printer - I think we should now only accept it if they
5041 get it right (tridge) */
5042 if (!CAN_PRINT(conn)) {
5043 reply_doserror(req, ERRDOS, ERRnoaccess);
5044 END_PROFILE(SMBsplretq);
5048 reply_outbuf(req, 2, 3);
5049 SSVAL(req->outbuf,smb_vwv0,0);
5050 SSVAL(req->outbuf,smb_vwv1,0);
5051 SCVAL(smb_buf(req->outbuf),0,1);
5052 SSVAL(smb_buf(req->outbuf),1,0);
5054 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5055 start_index, max_count));
5058 print_queue_struct *queue = NULL;
5059 print_status_struct status;
5060 int count = print_queue_status(SNUM(conn), &queue, &status);
5061 int num_to_get = ABS(max_count);
5062 int first = (max_count>0?start_index:start_index+max_count+1);
5068 num_to_get = MIN(num_to_get,count-first);
5071 for (i=first;i<first+num_to_get;i++) {
5075 srv_put_dos_date2(p,0,queue[i].time);
5076 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5077 SSVAL(p,5, queue[i].job);
5078 SIVAL(p,7,queue[i].size);
5080 srvstr_push(blob, req->flags2, p+12,
5081 queue[i].fs_user, 16, STR_ASCII);
5083 if (message_push_blob(
5086 blob, sizeof(blob))) == -1) {
5087 reply_nterror(req, NT_STATUS_NO_MEMORY);
5088 END_PROFILE(SMBsplretq);
5094 SSVAL(req->outbuf,smb_vwv0,count);
5095 SSVAL(req->outbuf,smb_vwv1,
5096 (max_count>0?first+count:first-1));
5097 SCVAL(smb_buf(req->outbuf),0,1);
5098 SSVAL(smb_buf(req->outbuf),1,28*count);
5103 DEBUG(3,("%d entries returned in queue\n",count));
5106 END_PROFILE(SMBsplretq);
5110 /****************************************************************************
5111 Reply to a printwrite.
5112 ****************************************************************************/
5114 void reply_printwrite(struct smb_request *req)
5116 connection_struct *conn = req->conn;
5121 START_PROFILE(SMBsplwr);
5124 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5125 END_PROFILE(SMBsplwr);
5129 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5131 if (!check_fsp(conn, req, fsp)) {
5132 END_PROFILE(SMBsplwr);
5136 if (!CAN_PRINT(conn)) {
5137 reply_doserror(req, ERRDOS, ERRnoaccess);
5138 END_PROFILE(SMBsplwr);
5142 if (!CHECK_WRITE(fsp)) {
5143 reply_doserror(req, ERRDOS, ERRbadaccess);
5144 END_PROFILE(SMBsplwr);
5148 numtowrite = SVAL(req->buf, 1);
5150 if (req->buflen < numtowrite + 3) {
5151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5152 END_PROFILE(SMBsplwr);
5156 data = (const char *)req->buf + 3;
5158 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5159 reply_unixerror(req, ERRHRD, ERRdiskfull);
5160 END_PROFILE(SMBsplwr);
5164 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5166 END_PROFILE(SMBsplwr);
5170 /****************************************************************************
5172 ****************************************************************************/
5174 void reply_mkdir(struct smb_request *req)
5176 connection_struct *conn = req->conn;
5177 struct smb_filename *smb_dname = NULL;
5178 char *directory = NULL;
5180 TALLOC_CTX *ctx = talloc_tos();
5182 START_PROFILE(SMBmkdir);
5184 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5185 STR_TERMINATE, &status);
5186 if (!NT_STATUS_IS_OK(status)) {
5187 reply_nterror(req, status);
5191 status = resolve_dfspath(ctx, conn,
5192 req->flags2 & FLAGS2_DFS_PATHNAMES,
5195 if (!NT_STATUS_IS_OK(status)) {
5196 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5197 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5198 ERRSRV, ERRbadpath);
5201 reply_nterror(req, status);
5205 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
5206 if (!NT_STATUS_IS_OK(status)) {
5207 reply_nterror(req, status);
5211 status = get_full_smb_filename(ctx, smb_dname, &directory);
5212 if (!NT_STATUS_IS_OK(status)) {
5213 reply_nterror(req, status);
5217 status = check_name(conn, directory);
5218 if (!NT_STATUS_IS_OK(status)) {
5219 reply_nterror(req, status);
5223 status = create_directory(conn, req, directory);
5225 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5227 if (!NT_STATUS_IS_OK(status)) {
5229 if (!use_nt_status()
5230 && NT_STATUS_EQUAL(status,
5231 NT_STATUS_OBJECT_NAME_COLLISION)) {
5233 * Yes, in the DOS error code case we get a
5234 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5235 * samba4 torture test.
5237 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5240 reply_nterror(req, status);
5244 reply_outbuf(req, 0, 0);
5246 DEBUG( 3, ( "mkdir %s\n", directory ) );
5248 TALLOC_FREE(smb_dname);
5249 END_PROFILE(SMBmkdir);
5253 /****************************************************************************
5254 Static function used by reply_rmdir to delete an entire directory
5255 tree recursively. Return True on ok, False on fail.
5256 ****************************************************************************/
5258 static bool recursive_rmdir(TALLOC_CTX *ctx,
5259 connection_struct *conn,
5262 const char *dname = NULL;
5266 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5272 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5273 char *fullname = NULL;
5275 if (ISDOT(dname) || ISDOTDOT(dname)) {
5279 if (!is_visible_file(conn, directory, dname, &st, False)) {
5283 /* Construct the full name. */
5284 fullname = talloc_asprintf(ctx,
5294 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5299 if(st.st_ex_mode & S_IFDIR) {
5300 if(!recursive_rmdir(ctx, conn, fullname)) {
5304 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5308 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5312 TALLOC_FREE(fullname);
5314 TALLOC_FREE(dir_hnd);
5318 /****************************************************************************
5319 The internals of the rmdir code - called elsewhere.
5320 ****************************************************************************/
5322 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5323 connection_struct *conn,
5324 const char *directory)
5329 /* Might be a symlink. */
5330 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5331 return map_nt_error_from_unix(errno);
5334 if (S_ISLNK(st.st_ex_mode)) {
5335 /* Is what it points to a directory ? */
5336 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5337 return map_nt_error_from_unix(errno);
5339 if (!(S_ISDIR(st.st_ex_mode))) {
5340 return NT_STATUS_NOT_A_DIRECTORY;
5342 ret = SMB_VFS_UNLINK(conn,directory);
5344 ret = SMB_VFS_RMDIR(conn,directory);
5347 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5348 FILE_NOTIFY_CHANGE_DIR_NAME,
5350 return NT_STATUS_OK;
5353 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5355 * Check to see if the only thing in this directory are
5356 * vetoed files/directories. If so then delete them and
5357 * retry. If we fail to delete any of them (and we *don't*
5358 * do a recursive delete) then fail the rmdir.
5362 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5363 directory, NULL, 0);
5365 if(dir_hnd == NULL) {
5370 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5371 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5373 if (!is_visible_file(conn, directory, dname, &st, False))
5375 if(!IS_VETO_PATH(conn, dname)) {
5376 TALLOC_FREE(dir_hnd);
5382 /* We only have veto files/directories.
5383 * Are we allowed to delete them ? */
5385 if(!lp_recursive_veto_delete(SNUM(conn))) {
5386 TALLOC_FREE(dir_hnd);
5391 /* Do a recursive delete. */
5392 RewindDir(dir_hnd,&dirpos);
5393 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5394 char *fullname = NULL;
5396 if (ISDOT(dname) || ISDOTDOT(dname)) {
5399 if (!is_visible_file(conn, directory, dname, &st, False)) {
5403 fullname = talloc_asprintf(ctx,
5413 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5416 if(st.st_ex_mode & S_IFDIR) {
5417 if(!recursive_rmdir(ctx, conn, fullname)) {
5420 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5423 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5426 TALLOC_FREE(fullname);
5428 TALLOC_FREE(dir_hnd);
5429 /* Retry the rmdir */
5430 ret = SMB_VFS_RMDIR(conn,directory);
5436 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5437 "%s\n", directory,strerror(errno)));
5438 return map_nt_error_from_unix(errno);
5441 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5442 FILE_NOTIFY_CHANGE_DIR_NAME,
5445 return NT_STATUS_OK;
5448 /****************************************************************************
5450 ****************************************************************************/
5452 void reply_rmdir(struct smb_request *req)
5454 connection_struct *conn = req->conn;
5455 struct smb_filename *smb_dname = NULL;
5456 char *directory = NULL;
5458 TALLOC_CTX *ctx = talloc_tos();
5460 START_PROFILE(SMBrmdir);
5462 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5463 STR_TERMINATE, &status);
5464 if (!NT_STATUS_IS_OK(status)) {
5465 reply_nterror(req, status);
5469 status = resolve_dfspath(ctx, conn,
5470 req->flags2 & FLAGS2_DFS_PATHNAMES,
5473 if (!NT_STATUS_IS_OK(status)) {
5474 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5475 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5476 ERRSRV, ERRbadpath);
5479 reply_nterror(req, status);
5483 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
5484 if (!NT_STATUS_IS_OK(status)) {
5485 reply_nterror(req, status);
5489 status = get_full_smb_filename(ctx, smb_dname, &directory);
5490 if (!NT_STATUS_IS_OK(status)) {
5491 reply_nterror(req, status);
5495 status = check_name(conn, directory);
5496 if (!NT_STATUS_IS_OK(status)) {
5497 reply_nterror(req, status);
5501 dptr_closepath(directory, req->smbpid);
5502 status = rmdir_internals(ctx, conn, directory);
5503 if (!NT_STATUS_IS_OK(status)) {
5504 reply_nterror(req, status);
5508 reply_outbuf(req, 0, 0);
5510 DEBUG( 3, ( "rmdir %s\n", directory ) );
5512 TALLOC_FREE(smb_dname);
5513 END_PROFILE(SMBrmdir);
5517 /*******************************************************************
5518 Resolve wildcards in a filename rename.
5519 ********************************************************************/
5521 static bool resolve_wildcards(TALLOC_CTX *ctx,
5526 char *name2_copy = NULL;
5531 char *p,*p2, *pname1, *pname2;
5533 name2_copy = talloc_strdup(ctx, name2);
5538 pname1 = strrchr_m(name1,'/');
5539 pname2 = strrchr_m(name2_copy,'/');
5541 if (!pname1 || !pname2) {
5545 /* Truncate the copy of name2 at the last '/' */
5548 /* Now go past the '/' */
5552 root1 = talloc_strdup(ctx, pname1);
5553 root2 = talloc_strdup(ctx, pname2);
5555 if (!root1 || !root2) {
5559 p = strrchr_m(root1,'.');
5562 ext1 = talloc_strdup(ctx, p+1);
5564 ext1 = talloc_strdup(ctx, "");
5566 p = strrchr_m(root2,'.');
5569 ext2 = talloc_strdup(ctx, p+1);
5571 ext2 = talloc_strdup(ctx, "");
5574 if (!ext1 || !ext2) {
5582 /* Hmmm. Should this be mb-aware ? */
5585 } else if (*p2 == '*') {
5587 root2 = talloc_asprintf(ctx, "%s%s",
5606 /* Hmmm. Should this be mb-aware ? */
5609 } else if (*p2 == '*') {
5611 ext2 = talloc_asprintf(ctx, "%s%s",
5627 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5632 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5644 /****************************************************************************
5645 Ensure open files have their names updated. Updated to notify other smbd's
5647 ****************************************************************************/
5649 static void rename_open_files(connection_struct *conn,
5650 struct share_mode_lock *lck,
5651 const char *newname)
5654 bool did_rename = False;
5656 for(fsp = file_find_di_first(lck->id); fsp;
5657 fsp = file_find_di_next(fsp)) {
5658 /* fsp_name is a relative path under the fsp. To change this for other
5659 sharepaths we need to manipulate relative paths. */
5660 /* TODO - create the absolute path and manipulate the newname
5661 relative to the sharepath. */
5662 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5665 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5666 fsp->fnum, file_id_string_tos(&fsp->file_id),
5667 fsp->fsp_name, newname ));
5668 string_set(&fsp->fsp_name, newname);
5673 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5674 file_id_string_tos(&lck->id), newname ));
5677 /* Send messages to all smbd's (not ourself) that the name has changed. */
5678 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5682 /****************************************************************************
5683 We need to check if the source path is a parent directory of the destination
5684 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5685 refuse the rename with a sharing violation. Under UNIX the above call can
5686 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5687 probably need to check that the client is a Windows one before disallowing
5688 this as a UNIX client (one with UNIX extensions) can know the source is a
5689 symlink and make this decision intelligently. Found by an excellent bug
5690 report from <AndyLiebman@aol.com>.
5691 ****************************************************************************/
5693 static bool rename_path_prefix_equal(const char *src, const char *dest)
5695 const char *psrc = src;
5696 const char *pdst = dest;
5699 if (psrc[0] == '.' && psrc[1] == '/') {
5702 if (pdst[0] == '.' && pdst[1] == '/') {
5705 if ((slen = strlen(psrc)) > strlen(pdst)) {
5708 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5712 * Do the notify calls from a rename
5715 static void notify_rename(connection_struct *conn, bool is_dir,
5716 const char *oldpath, const char *newpath)
5718 char *olddir, *newdir;
5719 const char *oldname, *newname;
5722 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5723 : FILE_NOTIFY_CHANGE_FILE_NAME;
5725 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5726 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5727 TALLOC_FREE(olddir);
5731 if (strcmp(olddir, newdir) == 0) {
5732 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5733 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5736 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5737 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5739 TALLOC_FREE(olddir);
5740 TALLOC_FREE(newdir);
5742 /* this is a strange one. w2k3 gives an additional event for
5743 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5744 files, but not directories */
5746 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5747 FILE_NOTIFY_CHANGE_ATTRIBUTES
5748 |FILE_NOTIFY_CHANGE_CREATION,
5753 /****************************************************************************
5754 Rename an open file - given an fsp.
5755 ****************************************************************************/
5757 NTSTATUS rename_internals_fsp(connection_struct *conn,
5760 const char *newname_last_component,
5762 bool replace_if_exists)
5764 TALLOC_CTX *ctx = talloc_tos();
5765 SMB_STRUCT_STAT sbuf, sbuf1;
5766 NTSTATUS status = NT_STATUS_OK;
5767 struct share_mode_lock *lck = NULL;
5768 bool dst_exists, old_is_stream, new_is_stream;
5772 status = check_name(conn, newname);
5773 if (!NT_STATUS_IS_OK(status)) {
5777 /* Ensure newname contains a '/' */
5778 if(strrchr_m(newname,'/') == 0) {
5779 newname = talloc_asprintf(ctx,
5783 return NT_STATUS_NO_MEMORY;
5788 * Check for special case with case preserving and not
5789 * case sensitive. If the old last component differs from the original
5790 * last component only by case, then we should allow
5791 * the rename (user is trying to change the case of the
5795 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5796 strequal(newname, fsp->fsp_name)) {
5798 char *newname_modified_last_component = NULL;
5801 * Get the last component of the modified name.
5802 * Note that we guarantee that newname contains a '/'
5805 p = strrchr_m(newname,'/');
5806 newname_modified_last_component = talloc_strdup(ctx,
5808 if (!newname_modified_last_component) {
5809 return NT_STATUS_NO_MEMORY;
5812 if(strcsequal(newname_modified_last_component,
5813 newname_last_component) == False) {
5815 * Replace the modified last component with
5818 *p = '\0'; /* Truncate at the '/' */
5819 newname = talloc_asprintf(ctx,
5822 newname_last_component);
5827 * If the src and dest names are identical - including case,
5828 * don't do the rename, just return success.
5831 if (strcsequal(fsp->fsp_name, newname)) {
5832 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5834 return NT_STATUS_OK;
5837 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5838 new_is_stream = is_ntfs_stream_name(newname);
5840 /* Return the correct error code if both names aren't streams. */
5841 if (!old_is_stream && new_is_stream) {
5842 return NT_STATUS_OBJECT_NAME_INVALID;
5845 if (old_is_stream && !new_is_stream) {
5846 return NT_STATUS_INVALID_PARAMETER;
5850 * Have vfs_object_exist also fill sbuf1
5852 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5854 if(!replace_if_exists && dst_exists) {
5855 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5856 fsp->fsp_name,newname));
5857 return NT_STATUS_OBJECT_NAME_COLLISION;
5861 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5862 files_struct *dst_fsp = file_find_di_first(fileid);
5863 /* The file can be open when renaming a stream */
5864 if (dst_fsp && !new_is_stream) {
5865 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5866 return NT_STATUS_ACCESS_DENIED;
5870 /* Ensure we have a valid stat struct for the source. */
5871 if (fsp->fh->fd != -1) {
5872 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5873 return map_nt_error_from_unix(errno);
5877 if (fsp->posix_open) {
5878 ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
5880 ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
5883 return map_nt_error_from_unix(errno);
5887 status = can_rename(conn, fsp, attrs, &sbuf);
5889 if (!NT_STATUS_IS_OK(status)) {
5890 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5891 nt_errstr(status), fsp->fsp_name,newname));
5892 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5893 status = NT_STATUS_ACCESS_DENIED;
5897 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5898 return NT_STATUS_ACCESS_DENIED;
5901 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5905 * We have the file open ourselves, so not being able to get the
5906 * corresponding share mode lock is a fatal error.
5909 SMB_ASSERT(lck != NULL);
5911 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5912 uint32 create_options = fsp->fh->private_options;
5914 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5915 fsp->fsp_name,newname));
5917 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5919 rename_open_files(conn, lck, newname);
5922 * A rename acts as a new file create w.r.t. allowing an initial delete
5923 * on close, probably because in Windows there is a new handle to the
5924 * new file. If initial delete on close was requested but not
5925 * originally set, we need to set it here. This is probably not 100% correct,
5926 * but will work for the CIFSFS client which in non-posix mode
5927 * depends on these semantics. JRA.
5930 if (create_options & FILE_DELETE_ON_CLOSE) {
5931 status = can_set_delete_on_close(fsp, True, 0);
5933 if (NT_STATUS_IS_OK(status)) {
5934 /* Note that here we set the *inital* delete on close flag,
5935 * not the regular one. The magic gets handled in close. */
5936 fsp->initial_delete_on_close = True;
5940 return NT_STATUS_OK;
5945 if (errno == ENOTDIR || errno == EISDIR) {
5946 status = NT_STATUS_OBJECT_NAME_COLLISION;
5948 status = map_nt_error_from_unix(errno);
5951 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5952 nt_errstr(status), fsp->fsp_name,newname));
5957 /****************************************************************************
5958 The guts of the rename command, split out so it may be called by the NT SMB
5960 ****************************************************************************/
5962 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5963 connection_struct *conn,
5964 struct smb_request *req,
5965 const char *name_in,
5966 const char *newname_in,
5968 bool replace_if_exists,
5971 uint32_t access_mask)
5973 struct smb_filename *smb_fname = NULL;
5974 struct smb_filename *smb_fname_new = NULL;
5975 char *directory = NULL;
5978 char *newname = NULL;
5981 NTSTATUS status = NT_STATUS_OK;
5982 struct smb_Dir *dir_hnd = NULL;
5985 int create_options = 0;
5986 bool posix_pathnames = lp_posix_pathnames();
5988 status = unix_convert(ctx, conn, name_in, &smb_fname,
5989 src_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
5990 if (!NT_STATUS_IS_OK(status)) {
5994 status = get_full_smb_filename(ctx, smb_fname, &name);
5995 if (!NT_STATUS_IS_OK(status)) {
5999 status = unix_convert(ctx, conn, newname_in, &smb_fname_new,
6001 (dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0)));
6002 if (!NT_STATUS_IS_OK(status)) {
6006 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
6007 if (!NT_STATUS_IS_OK(status)) {
6012 * Split the old name into directory and last component
6013 * strings. Note that unix_convert may have stripped off a
6014 * leading ./ from both name and newname if the rename is
6015 * at the root of the share. We need to make sure either both
6016 * name and newname contain a / character or neither of them do
6017 * as this is checked in resolve_wildcards().
6020 p = strrchr_m(name,'/');
6022 directory = talloc_strdup(ctx, ".");
6024 status = NT_STATUS_NO_MEMORY;
6030 directory = talloc_strdup(ctx, name);
6032 status = NT_STATUS_NO_MEMORY;
6036 *p = '/'; /* Replace needed for exceptional test below. */
6040 * We should only check the mangled cache
6041 * here if unix_convert failed. This means
6042 * that the path in 'mask' doesn't exist
6043 * on the file system and so we need to look
6044 * for a possible mangle. This patch from
6045 * Tine Smukavec <valentin.smukavec@hermes.si>.
6048 if (!VALID_STAT(smb_fname->st) && mangle_is_mangled(mask, conn->params)) {
6049 char *new_mask = NULL;
6050 mangle_lookup_name_from_8_3(ctx,
6059 if (!src_has_wild) {
6063 * No wildcards - just process the one file.
6065 /* Add a terminating '/' to the directory name. */
6066 directory = talloc_asprintf_append(directory,
6070 status = NT_STATUS_NO_MEMORY;
6074 /* Ensure newname contains a '/' also */
6075 if(strrchr_m(newname,'/') == 0) {
6076 newname = talloc_asprintf(ctx,
6080 status = NT_STATUS_NO_MEMORY;
6085 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6086 "case_preserve = %d, short case preserve = %d, "
6087 "directory = %s, newname = %s, "
6088 "last_component_dest = %s\n",
6089 conn->case_sensitive, conn->case_preserve,
6090 conn->short_case_preserve, directory,
6091 newname, smb_fname_new->original_lcomp));
6093 /* The dest name still may have wildcards. */
6094 if (dest_has_wild) {
6095 char *mod_newname = NULL;
6096 if (!resolve_wildcards(ctx,
6097 directory,newname,&mod_newname)) {
6098 DEBUG(6, ("rename_internals: resolve_wildcards "
6102 status = NT_STATUS_NO_MEMORY;
6105 newname = mod_newname;
6108 ZERO_STRUCT(smb_fname->st);
6109 if (posix_pathnames) {
6110 SMB_VFS_LSTAT(conn, directory, &smb_fname->st);
6112 SMB_VFS_STAT(conn, directory, &smb_fname->st);
6115 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6116 create_options |= FILE_DIRECTORY_FILE;
6119 status = SMB_VFS_CREATE_FILE(
6122 0, /* root_dir_fid */
6123 directory, /* fname */
6124 0, /* create_file_flags */
6125 access_mask, /* access_mask */
6126 (FILE_SHARE_READ | /* share_access */
6128 FILE_OPEN, /* create_disposition*/
6129 create_options, /* create_options */
6130 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6131 0, /* oplock_request */
6132 0, /* allocation_size */
6137 &smb_fname->st); /* psbuf */
6139 if (!NT_STATUS_IS_OK(status)) {
6140 DEBUG(3, ("Could not open rename source %s: %s\n",
6141 directory, nt_errstr(status)));
6145 status = rename_internals_fsp(conn, fsp, newname,
6146 smb_fname_new->original_lcomp,
6147 attrs, replace_if_exists);
6149 close_file(req, fsp, NORMAL_CLOSE);
6151 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6152 nt_errstr(status), directory,newname));
6158 * Wildcards - process each file that matches.
6160 if (strequal(mask,"????????.???")) {
6165 status = check_name(conn, directory);
6166 if (!NT_STATUS_IS_OK(status)) {
6170 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
6171 if (dir_hnd == NULL) {
6172 status = map_nt_error_from_unix(errno);
6176 status = NT_STATUS_NO_SUCH_FILE;
6178 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6179 * - gentest fix. JRA
6182 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname->st))) {
6183 files_struct *fsp = NULL;
6185 char *destname = NULL;
6186 bool sysdir_entry = False;
6188 /* Quick check for "." and ".." */
6189 if (ISDOT(dname) || ISDOTDOT(dname)) {
6191 sysdir_entry = True;
6197 if (!is_visible_file(conn, directory, dname, &smb_fname->st,
6202 if(!mask_match(dname, mask, conn->case_sensitive)) {
6207 status = NT_STATUS_OBJECT_NAME_INVALID;
6211 fname = talloc_asprintf(ctx,
6216 status = NT_STATUS_NO_MEMORY;
6220 if (!resolve_wildcards(ctx,
6221 fname,newname,&destname)) {
6222 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6228 status = NT_STATUS_NO_MEMORY;
6232 ZERO_STRUCT(smb_fname->st);
6233 if (posix_pathnames) {
6234 SMB_VFS_LSTAT(conn, fname, &smb_fname->st);
6236 SMB_VFS_STAT(conn, fname, &smb_fname->st);
6241 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6242 create_options |= FILE_DIRECTORY_FILE;
6245 status = SMB_VFS_CREATE_FILE(
6248 0, /* root_dir_fid */
6250 0, /* create_file_flags */
6251 access_mask, /* access_mask */
6252 (FILE_SHARE_READ | /* share_access */
6254 FILE_OPEN, /* create_disposition*/
6255 create_options, /* create_options */
6256 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6257 0, /* oplock_request */
6258 0, /* allocation_size */
6263 &smb_fname->st); /* psbuf */
6265 if (!NT_STATUS_IS_OK(status)) {
6266 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6267 "returned %s rename %s -> %s\n",
6268 nt_errstr(status), directory, newname));
6272 status = rename_internals_fsp(conn, fsp, destname, dname,
6273 attrs, replace_if_exists);
6275 close_file(req, fsp, NORMAL_CLOSE);
6277 if (!NT_STATUS_IS_OK(status)) {
6278 DEBUG(3, ("rename_internals_fsp returned %s for "
6279 "rename %s -> %s\n", nt_errstr(status),
6280 directory, newname));
6286 DEBUG(3,("rename_internals: doing rename on %s -> "
6287 "%s\n",fname,destname));
6290 TALLOC_FREE(destname);
6292 TALLOC_FREE(dir_hnd);
6294 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6295 status = map_nt_error_from_unix(errno);
6299 TALLOC_FREE(smb_fname);
6300 TALLOC_FREE(smb_fname_new);
6304 /****************************************************************************
6306 ****************************************************************************/
6308 void reply_mv(struct smb_request *req)
6310 connection_struct *conn = req->conn;
6312 char *newname = NULL;
6316 bool src_has_wcard = False;
6317 bool dest_has_wcard = False;
6318 TALLOC_CTX *ctx = talloc_tos();
6320 START_PROFILE(SMBmv);
6323 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6328 attrs = SVAL(req->vwv+0, 0);
6330 p = (const char *)req->buf + 1;
6331 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6332 &status, &src_has_wcard);
6333 if (!NT_STATUS_IS_OK(status)) {
6334 reply_nterror(req, status);
6339 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6340 &status, &dest_has_wcard);
6341 if (!NT_STATUS_IS_OK(status)) {
6342 reply_nterror(req, status);
6347 status = resolve_dfspath_wcard(ctx, conn,
6348 req->flags2 & FLAGS2_DFS_PATHNAMES,
6352 if (!NT_STATUS_IS_OK(status)) {
6353 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6354 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6355 ERRSRV, ERRbadpath);
6359 reply_nterror(req, status);
6364 status = resolve_dfspath_wcard(ctx, conn,
6365 req->flags2 & FLAGS2_DFS_PATHNAMES,
6369 if (!NT_STATUS_IS_OK(status)) {
6370 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6371 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6372 ERRSRV, ERRbadpath);
6376 reply_nterror(req, status);
6381 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6383 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6384 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6385 if (!NT_STATUS_IS_OK(status)) {
6386 if (open_was_deferred(req->mid)) {
6387 /* We have re-scheduled this call. */
6391 reply_nterror(req, status);
6396 reply_outbuf(req, 0, 0);
6402 /*******************************************************************
6403 Copy a file as part of a reply_copy.
6404 ******************************************************************/
6407 * TODO: check error codes on all callers
6410 NTSTATUS copy_file(TALLOC_CTX *ctx,
6411 connection_struct *conn,
6416 bool target_is_directory)
6418 SMB_STRUCT_STAT src_sbuf, sbuf2;
6420 files_struct *fsp1,*fsp2;
6423 uint32 new_create_disposition;
6426 dest = talloc_strdup(ctx, dest1);
6428 return NT_STATUS_NO_MEMORY;
6430 if (target_is_directory) {
6431 const char *p = strrchr_m(src,'/');
6437 dest = talloc_asprintf_append(dest,
6441 return NT_STATUS_NO_MEMORY;
6445 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6447 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6450 if (!target_is_directory && count) {
6451 new_create_disposition = FILE_OPEN;
6453 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6454 NULL, NULL, &new_create_disposition, NULL)) {
6456 return NT_STATUS_INVALID_PARAMETER;
6460 status = SMB_VFS_CREATE_FILE(
6463 0, /* root_dir_fid */
6465 0, /* create_file_flags */
6466 FILE_GENERIC_READ, /* access_mask */
6467 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6468 FILE_OPEN, /* create_disposition*/
6469 0, /* create_options */
6470 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6471 INTERNAL_OPEN_ONLY, /* oplock_request */
6472 0, /* allocation_size */
6477 &src_sbuf); /* psbuf */
6479 if (!NT_STATUS_IS_OK(status)) {
6484 dosattrs = dos_mode(conn, src, &src_sbuf);
6485 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6486 ZERO_STRUCTP(&sbuf2);
6489 status = SMB_VFS_CREATE_FILE(
6492 0, /* root_dir_fid */
6494 0, /* create_file_flags */
6495 FILE_GENERIC_WRITE, /* access_mask */
6496 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6497 new_create_disposition, /* create_disposition*/
6498 0, /* create_options */
6499 dosattrs, /* file_attributes */
6500 INTERNAL_OPEN_ONLY, /* oplock_request */
6501 0, /* allocation_size */
6506 &sbuf2); /* psbuf */
6510 if (!NT_STATUS_IS_OK(status)) {
6511 close_file(NULL, fsp1, ERROR_CLOSE);
6515 if ((ofun&3) == 1) {
6516 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6517 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6519 * Stop the copy from occurring.
6522 src_sbuf.st_ex_size = 0;
6526 if (src_sbuf.st_ex_size) {
6527 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_ex_size);
6530 close_file(NULL, fsp1, NORMAL_CLOSE);
6532 /* Ensure the modtime is set correctly on the destination file. */
6533 set_close_write_time(fsp2, src_sbuf.st_ex_mtime);
6536 * As we are opening fsp1 read-only we only expect
6537 * an error on close on fsp2 if we are out of space.
6538 * Thus we don't look at the error return from the
6541 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6543 if (!NT_STATUS_IS_OK(status)) {
6547 if (ret != (SMB_OFF_T)src_sbuf.st_ex_size) {
6548 return NT_STATUS_DISK_FULL;
6551 return NT_STATUS_OK;
6554 /****************************************************************************
6555 Reply to a file copy.
6556 ****************************************************************************/
6558 void reply_copy(struct smb_request *req)
6560 connection_struct *conn = req->conn;
6561 struct smb_filename *smb_fname = NULL;
6562 struct smb_filename *smb_fname_new = NULL;
6564 char *newname = NULL;
6565 char *directory = NULL;
6566 const char *mask = NULL;
6567 const char mask_star[] = "*";
6570 int error = ERRnoaccess;
6575 bool target_is_directory=False;
6576 bool source_has_wild = False;
6577 bool dest_has_wild = False;
6579 TALLOC_CTX *ctx = talloc_tos();
6581 START_PROFILE(SMBcopy);
6584 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6588 tid2 = SVAL(req->vwv+0, 0);
6589 ofun = SVAL(req->vwv+1, 0);
6590 flags = SVAL(req->vwv+2, 0);
6592 p = (const char *)req->buf;
6593 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6594 &status, &source_has_wild);
6595 if (!NT_STATUS_IS_OK(status)) {
6596 reply_nterror(req, status);
6599 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6600 &status, &dest_has_wild);
6601 if (!NT_STATUS_IS_OK(status)) {
6602 reply_nterror(req, status);
6606 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6608 if (tid2 != conn->cnum) {
6609 /* can't currently handle inter share copies XXXX */
6610 DEBUG(3,("Rejecting inter-share copy\n"));
6611 reply_doserror(req, ERRSRV, ERRinvdevice);
6615 status = resolve_dfspath_wcard(ctx, conn,
6616 req->flags2 & FLAGS2_DFS_PATHNAMES,
6620 if (!NT_STATUS_IS_OK(status)) {
6621 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6622 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6623 ERRSRV, ERRbadpath);
6626 reply_nterror(req, status);
6630 status = resolve_dfspath_wcard(ctx, conn,
6631 req->flags2 & FLAGS2_DFS_PATHNAMES,
6635 if (!NT_STATUS_IS_OK(status)) {
6636 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6637 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6638 ERRSRV, ERRbadpath);
6641 reply_nterror(req, status);
6645 status = unix_convert(ctx, conn, name, &smb_fname,
6646 source_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6647 if (!NT_STATUS_IS_OK(status)) {
6648 reply_nterror(req, status);
6652 status = get_full_smb_filename(ctx, smb_fname, &name);
6653 if (!NT_STATUS_IS_OK(status)) {
6654 reply_nterror(req, status);
6658 status = unix_convert(ctx, conn, newname, &smb_fname_new,
6659 dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6660 if (!NT_STATUS_IS_OK(status)) {
6661 reply_nterror(req, status);
6665 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
6666 if (!NT_STATUS_IS_OK(status)) {
6667 reply_nterror(req, status);
6671 target_is_directory = VALID_STAT_OF_DIR(smb_fname_new->st);
6673 if ((flags&1) && target_is_directory) {
6674 reply_doserror(req, ERRDOS, ERRbadfile);
6678 if ((flags&2) && !target_is_directory) {
6679 reply_doserror(req, ERRDOS, ERRbadpath);
6683 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname->st)) {
6684 /* wants a tree copy! XXXX */
6685 DEBUG(3,("Rejecting tree copy\n"));
6686 reply_doserror(req, ERRSRV, ERRerror);
6690 p = strrchr_m(name,'/');
6692 directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
6695 directory = talloc_strdup(ctx, "./");
6700 reply_nterror(req, NT_STATUS_NO_MEMORY);
6705 * We should only check the mangled cache
6706 * here if unix_convert failed. This means
6707 * that the path in 'mask' doesn't exist
6708 * on the file system and so we need to look
6709 * for a possible mangle. This patch from
6710 * Tine Smukavec <valentin.smukavec@hermes.si>.
6713 if (!VALID_STAT(smb_fname->st) &&
6714 mangle_is_mangled(mask, conn->params)) {
6715 char *new_mask = NULL;
6716 mangle_lookup_name_from_8_3(ctx,
6725 if (!source_has_wild) {
6726 directory = talloc_asprintf_append(directory,
6729 if (dest_has_wild) {
6730 char *mod_newname = NULL;
6731 if (!resolve_wildcards(ctx,
6732 directory,newname,&mod_newname)) {
6733 reply_nterror(req, NT_STATUS_NO_MEMORY);
6736 newname = mod_newname;
6739 status = check_name(conn, directory);
6740 if (!NT_STATUS_IS_OK(status)) {
6741 reply_nterror(req, status);
6745 status = check_name(conn, newname);
6746 if (!NT_STATUS_IS_OK(status)) {
6747 reply_nterror(req, status);
6751 status = copy_file(ctx,conn,directory,newname,ofun,
6752 count,target_is_directory);
6754 if(!NT_STATUS_IS_OK(status)) {
6755 reply_nterror(req, status);
6761 struct smb_Dir *dir_hnd = NULL;
6762 const char *dname = NULL;
6765 if (strequal(mask,"????????.???")) {
6769 status = check_name(conn, directory);
6770 if (!NT_STATUS_IS_OK(status)) {
6771 reply_nterror(req, status);
6775 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6776 if (dir_hnd == NULL) {
6777 status = map_nt_error_from_unix(errno);
6778 reply_nterror(req, status);
6784 while ((dname = ReadDirName(dir_hnd, &offset,
6786 char *destname = NULL;
6789 if (ISDOT(dname) || ISDOTDOT(dname)) {
6793 if (!is_visible_file(conn, directory, dname,
6794 &smb_fname->st, False)) {
6798 if(!mask_match(dname, mask, conn->case_sensitive)) {
6802 error = ERRnoaccess;
6803 fname = talloc_asprintf(ctx,
6808 TALLOC_FREE(dir_hnd);
6809 reply_nterror(req, NT_STATUS_NO_MEMORY);
6813 if (!resolve_wildcards(ctx,
6814 fname,newname,&destname)) {
6818 TALLOC_FREE(dir_hnd);
6819 reply_nterror(req, NT_STATUS_NO_MEMORY);
6823 status = check_name(conn, fname);
6824 if (!NT_STATUS_IS_OK(status)) {
6825 TALLOC_FREE(dir_hnd);
6826 reply_nterror(req, status);
6830 status = check_name(conn, destname);
6831 if (!NT_STATUS_IS_OK(status)) {
6832 TALLOC_FREE(dir_hnd);
6833 reply_nterror(req, status);
6837 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6839 status = copy_file(ctx,conn,fname,destname,ofun,
6840 count,target_is_directory);
6841 if (NT_STATUS_IS_OK(status)) {
6845 TALLOC_FREE(destname);
6847 TALLOC_FREE(dir_hnd);
6852 /* Error on close... */
6854 reply_unixerror(req, ERRHRD, ERRgeneral);
6858 reply_doserror(req, ERRDOS, error);
6862 reply_outbuf(req, 1, 0);
6863 SSVAL(req->outbuf,smb_vwv0,count);
6865 TALLOC_FREE(smb_fname);
6866 TALLOC_FREE(smb_fname_new);
6867 END_PROFILE(SMBcopy);
6872 #define DBGC_CLASS DBGC_LOCKING
6874 /****************************************************************************
6875 Get a lock pid, dealing with large count requests.
6876 ****************************************************************************/
6878 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6879 bool large_file_format)
6881 if(!large_file_format)
6882 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6884 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6887 /****************************************************************************
6888 Get a lock count, dealing with large count requests.
6889 ****************************************************************************/
6891 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6892 bool large_file_format)
6896 if(!large_file_format) {
6897 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6900 #if defined(HAVE_LONGLONG)
6901 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6902 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6903 #else /* HAVE_LONGLONG */
6906 * NT4.x seems to be broken in that it sends large file (64 bit)
6907 * lockingX calls even if the CAP_LARGE_FILES was *not*
6908 * negotiated. For boxes without large unsigned ints truncate the
6909 * lock count by dropping the top 32 bits.
6912 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6913 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6914 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6915 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6916 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6919 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6920 #endif /* HAVE_LONGLONG */
6926 #if !defined(HAVE_LONGLONG)
6927 /****************************************************************************
6928 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6929 ****************************************************************************/
6931 static uint32 map_lock_offset(uint32 high, uint32 low)
6935 uint32 highcopy = high;
6938 * Try and find out how many significant bits there are in high.
6941 for(i = 0; highcopy; i++)
6945 * We use 31 bits not 32 here as POSIX
6946 * lock offsets may not be negative.
6949 mask = (~0) << (31 - i);
6952 return 0; /* Fail. */
6958 #endif /* !defined(HAVE_LONGLONG) */
6960 /****************************************************************************
6961 Get a lock offset, dealing with large offset requests.
6962 ****************************************************************************/
6964 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6965 bool large_file_format, bool *err)
6967 uint64_t offset = 0;
6971 if(!large_file_format) {
6972 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6975 #if defined(HAVE_LONGLONG)
6976 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6977 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6978 #else /* HAVE_LONGLONG */
6981 * NT4.x seems to be broken in that it sends large file (64 bit)
6982 * lockingX calls even if the CAP_LARGE_FILES was *not*
6983 * negotiated. For boxes without large unsigned ints mangle the
6984 * lock offset by mapping the top 32 bits onto the lower 32.
6987 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6988 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6989 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6992 if((new_low = map_lock_offset(high, low)) == 0) {
6994 return (uint64_t)-1;
6997 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6998 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6999 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7000 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7003 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7004 #endif /* HAVE_LONGLONG */
7010 /****************************************************************************
7011 Reply to a lockingX request.
7012 ****************************************************************************/
7014 void reply_lockingX(struct smb_request *req)
7016 connection_struct *conn = req->conn;
7018 unsigned char locktype;
7019 unsigned char oplocklevel;
7022 uint64_t count = 0, offset = 0;
7026 const uint8_t *data;
7027 bool large_file_format;
7029 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7031 START_PROFILE(SMBlockingX);
7034 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7035 END_PROFILE(SMBlockingX);
7039 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7040 locktype = CVAL(req->vwv+3, 0);
7041 oplocklevel = CVAL(req->vwv+3, 1);
7042 num_ulocks = SVAL(req->vwv+6, 0);
7043 num_locks = SVAL(req->vwv+7, 0);
7044 lock_timeout = IVAL(req->vwv+4, 0);
7045 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7047 if (!check_fsp(conn, req, fsp)) {
7048 END_PROFILE(SMBlockingX);
7054 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7055 /* we don't support these - and CANCEL_LOCK makes w2k
7056 and XP reboot so I don't really want to be
7057 compatible! (tridge) */
7058 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7059 END_PROFILE(SMBlockingX);
7063 /* Check if this is an oplock break on a file
7064 we have granted an oplock on.
7066 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7067 /* Client can insist on breaking to none. */
7068 bool break_to_none = (oplocklevel == 0);
7071 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7072 "for fnum = %d\n", (unsigned int)oplocklevel,
7076 * Make sure we have granted an exclusive or batch oplock on
7080 if (fsp->oplock_type == 0) {
7082 /* The Samba4 nbench simulator doesn't understand
7083 the difference between break to level2 and break
7084 to none from level2 - it sends oplock break
7085 replies in both cases. Don't keep logging an error
7086 message here - just ignore it. JRA. */
7088 DEBUG(5,("reply_lockingX: Error : oplock break from "
7089 "client for fnum = %d (oplock=%d) and no "
7090 "oplock granted on this file (%s).\n",
7091 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
7093 /* if this is a pure oplock break request then don't
7095 if (num_locks == 0 && num_ulocks == 0) {
7096 END_PROFILE(SMBlockingX);
7099 END_PROFILE(SMBlockingX);
7100 reply_doserror(req, ERRDOS, ERRlock);
7105 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7107 result = remove_oplock(fsp);
7109 result = downgrade_oplock(fsp);
7113 DEBUG(0, ("reply_lockingX: error in removing "
7114 "oplock on file %s\n", fsp->fsp_name));
7115 /* Hmmm. Is this panic justified? */
7116 smb_panic("internal tdb error");
7119 reply_to_oplock_break_requests(fsp);
7121 /* if this is a pure oplock break request then don't send a
7123 if (num_locks == 0 && num_ulocks == 0) {
7124 /* Sanity check - ensure a pure oplock break is not a
7126 if(CVAL(req->vwv+0, 0) != 0xff)
7127 DEBUG(0,("reply_lockingX: Error : pure oplock "
7128 "break is a chained %d request !\n",
7129 (unsigned int)CVAL(req->vwv+0, 0)));
7130 END_PROFILE(SMBlockingX);
7136 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7137 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7138 END_PROFILE(SMBlockingX);
7142 /* Data now points at the beginning of the list
7143 of smb_unlkrng structs */
7144 for(i = 0; i < (int)num_ulocks; i++) {
7145 lock_pid = get_lock_pid( data, i, large_file_format);
7146 count = get_lock_count( data, i, large_file_format);
7147 offset = get_lock_offset( data, i, large_file_format, &err);
7150 * There is no error code marked "stupid client bug".... :-).
7153 END_PROFILE(SMBlockingX);
7154 reply_doserror(req, ERRDOS, ERRnoaccess);
7158 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
7159 "pid %u, file %s\n", (double)offset, (double)count,
7160 (unsigned int)lock_pid, fsp->fsp_name ));
7162 status = do_unlock(smbd_messaging_context(),
7169 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
7170 nt_errstr(status)));
7172 if (NT_STATUS_V(status)) {
7173 END_PROFILE(SMBlockingX);
7174 reply_nterror(req, status);
7179 /* Setup the timeout in seconds. */
7181 if (!lp_blocking_locks(SNUM(conn))) {
7185 /* Now do any requested locks */
7186 data += ((large_file_format ? 20 : 10)*num_ulocks);
7188 /* Data now points at the beginning of the list
7189 of smb_lkrng structs */
7191 for(i = 0; i < (int)num_locks; i++) {
7192 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
7193 READ_LOCK:WRITE_LOCK);
7194 lock_pid = get_lock_pid( data, i, large_file_format);
7195 count = get_lock_count( data, i, large_file_format);
7196 offset = get_lock_offset( data, i, large_file_format, &err);
7199 * There is no error code marked "stupid client bug".... :-).
7202 END_PROFILE(SMBlockingX);
7203 reply_doserror(req, ERRDOS, ERRnoaccess);
7207 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
7208 "%u, file %s timeout = %d\n", (double)offset,
7209 (double)count, (unsigned int)lock_pid,
7210 fsp->fsp_name, (int)lock_timeout ));
7212 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7213 struct blocking_lock_record *blr = NULL;
7215 if (lp_blocking_locks(SNUM(conn))) {
7217 /* Schedule a message to ourselves to
7218 remove the blocking lock record and
7219 return the right error. */
7221 blr = blocking_lock_cancel(fsp,
7227 NT_STATUS_FILE_LOCK_CONFLICT);
7229 END_PROFILE(SMBlockingX);
7234 ERRcancelviolation));
7238 /* Remove a matching pending lock. */
7239 status = do_lock_cancel(fsp,
7246 bool blocking_lock = lock_timeout ? True : False;
7247 bool defer_lock = False;
7248 struct byte_range_lock *br_lck;
7249 uint32 block_smbpid;
7251 br_lck = do_lock(smbd_messaging_context(),
7263 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7264 /* Windows internal resolution for blocking locks seems
7265 to be about 200ms... Don't wait for less than that. JRA. */
7266 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7267 lock_timeout = lp_lock_spin_time();
7272 /* This heuristic seems to match W2K3 very well. If a
7273 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7274 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7275 far as I can tell. Replacement for do_lock_spin(). JRA. */
7277 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7278 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7280 lock_timeout = lp_lock_spin_time();
7283 if (br_lck && defer_lock) {
7285 * A blocking lock was requested. Package up
7286 * this smb into a queued request and push it
7287 * onto the blocking lock queue.
7289 if(push_blocking_lock_request(br_lck,
7300 TALLOC_FREE(br_lck);
7301 END_PROFILE(SMBlockingX);
7306 TALLOC_FREE(br_lck);
7309 if (NT_STATUS_V(status)) {
7310 END_PROFILE(SMBlockingX);
7311 reply_nterror(req, status);
7316 /* If any of the above locks failed, then we must unlock
7317 all of the previous locks (X/Open spec). */
7319 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7323 * Ensure we don't do a remove on the lock that just failed,
7324 * as under POSIX rules, if we have a lock already there, we
7325 * will delete it (and we shouldn't) .....
7327 for(i--; i >= 0; i--) {
7328 lock_pid = get_lock_pid( data, i, large_file_format);
7329 count = get_lock_count( data, i, large_file_format);
7330 offset = get_lock_offset( data, i, large_file_format,
7334 * There is no error code marked "stupid client
7338 END_PROFILE(SMBlockingX);
7339 reply_doserror(req, ERRDOS, ERRnoaccess);
7343 do_unlock(smbd_messaging_context(),
7350 END_PROFILE(SMBlockingX);
7351 reply_nterror(req, status);
7355 reply_outbuf(req, 2, 0);
7357 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7358 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7360 END_PROFILE(SMBlockingX);
7365 #define DBGC_CLASS DBGC_ALL
7367 /****************************************************************************
7368 Reply to a SMBreadbmpx (read block multiplex) request.
7369 Always reply with an error, if someone has a platform really needs this,
7370 please contact vl@samba.org
7371 ****************************************************************************/
7373 void reply_readbmpx(struct smb_request *req)
7375 START_PROFILE(SMBreadBmpx);
7376 reply_doserror(req, ERRSRV, ERRuseSTD);
7377 END_PROFILE(SMBreadBmpx);
7381 /****************************************************************************
7382 Reply to a SMBreadbs (read block multiplex secondary) request.
7383 Always reply with an error, if someone has a platform really needs this,
7384 please contact vl@samba.org
7385 ****************************************************************************/
7387 void reply_readbs(struct smb_request *req)
7389 START_PROFILE(SMBreadBs);
7390 reply_doserror(req, ERRSRV, ERRuseSTD);
7391 END_PROFILE(SMBreadBs);
7395 /****************************************************************************
7396 Reply to a SMBsetattrE.
7397 ****************************************************************************/
7399 void reply_setattrE(struct smb_request *req)
7401 connection_struct *conn = req->conn;
7402 struct smb_file_time ft;
7404 SMB_STRUCT_STAT sbuf;
7407 START_PROFILE(SMBsetattrE);
7411 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7412 END_PROFILE(SMBsetattrE);
7416 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7418 if(!fsp || (fsp->conn != conn)) {
7419 reply_doserror(req, ERRDOS, ERRbadfid);
7420 END_PROFILE(SMBsetattrE);
7426 * Convert the DOS times into unix times.
7429 ft.atime = convert_time_t_to_timespec(
7430 srv_make_unix_date2(req->vwv+3));
7431 ft.mtime = convert_time_t_to_timespec(
7432 srv_make_unix_date2(req->vwv+5));
7433 ft.create_time = convert_time_t_to_timespec(
7434 srv_make_unix_date2(req->vwv+1));
7436 reply_outbuf(req, 0, 0);
7439 * Patch from Ray Frush <frush@engr.colostate.edu>
7440 * Sometimes times are sent as zero - ignore them.
7443 /* Ensure we have a valid stat struct for the source. */
7444 if (fsp->fh->fd != -1) {
7445 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7446 status = map_nt_error_from_unix(errno);
7447 reply_nterror(req, status);
7448 END_PROFILE(SMBsetattrE);
7454 if (fsp->posix_open) {
7455 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
7457 ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
7460 status = map_nt_error_from_unix(errno);
7461 reply_nterror(req, status);
7462 END_PROFILE(SMBsetattrE);
7467 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7469 if (!NT_STATUS_IS_OK(status)) {
7470 reply_doserror(req, ERRDOS, ERRnoaccess);
7471 END_PROFILE(SMBsetattrE);
7475 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7478 (unsigned int)ft.atime.tv_sec,
7479 (unsigned int)ft.mtime.tv_sec,
7480 (unsigned int)ft.create_time.tv_sec
7483 END_PROFILE(SMBsetattrE);
7488 /* Back from the dead for OS/2..... JRA. */
7490 /****************************************************************************
7491 Reply to a SMBwritebmpx (write block multiplex primary) request.
7492 Always reply with an error, if someone has a platform really needs this,
7493 please contact vl@samba.org
7494 ****************************************************************************/
7496 void reply_writebmpx(struct smb_request *req)
7498 START_PROFILE(SMBwriteBmpx);
7499 reply_doserror(req, ERRSRV, ERRuseSTD);
7500 END_PROFILE(SMBwriteBmpx);
7504 /****************************************************************************
7505 Reply to a SMBwritebs (write block multiplex secondary) request.
7506 Always reply with an error, if someone has a platform really needs this,
7507 please contact vl@samba.org
7508 ****************************************************************************/
7510 void reply_writebs(struct smb_request *req)
7512 START_PROFILE(SMBwriteBs);
7513 reply_doserror(req, ERRSRV, ERRuseSTD);
7514 END_PROFILE(SMBwriteBs);
7518 /****************************************************************************
7519 Reply to a SMBgetattrE.
7520 ****************************************************************************/
7522 void reply_getattrE(struct smb_request *req)
7524 connection_struct *conn = req->conn;
7525 SMB_STRUCT_STAT sbuf;
7528 struct timespec create_ts;
7530 START_PROFILE(SMBgetattrE);
7533 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7534 END_PROFILE(SMBgetattrE);
7538 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7540 if(!fsp || (fsp->conn != conn)) {
7541 reply_doserror(req, ERRDOS, ERRbadfid);
7542 END_PROFILE(SMBgetattrE);
7546 /* Do an fstat on this file */
7547 if(fsp_stat(fsp, &sbuf)) {
7548 reply_unixerror(req, ERRDOS, ERRnoaccess);
7549 END_PROFILE(SMBgetattrE);
7553 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7556 * Convert the times into dos times. Set create
7557 * date to be last modify date as UNIX doesn't save
7561 reply_outbuf(req, 11, 0);
7563 create_ts = sbuf.st_ex_btime;
7564 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7565 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7566 convert_timespec_to_time_t(sbuf.st_ex_atime));
7567 /* Should we check pending modtime here ? JRA */
7568 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7569 convert_timespec_to_time_t(sbuf.st_ex_mtime));
7572 SIVAL(req->outbuf, smb_vwv6, 0);
7573 SIVAL(req->outbuf, smb_vwv8, 0);
7575 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7576 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_ex_size);
7577 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7579 SSVAL(req->outbuf,smb_vwv10, mode);
7581 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7583 END_PROFILE(SMBgetattrE);