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(sconn, 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 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
992 status = filename_convert(ctx,
994 req->flags2 & FLAGS2_DFS_PATHNAMES,
999 if (!NT_STATUS_IS_OK(status)) {
1000 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1001 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1002 ERRSRV, ERRbadpath);
1003 END_PROFILE(SMBcheckpath);
1009 if (!VALID_STAT(smb_fname->st) &&
1010 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1011 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1012 smb_fname_str_dbg(smb_fname), strerror(errno)));
1013 status = map_nt_error_from_unix(errno);
1017 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1018 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1019 ERRDOS, ERRbadpath);
1023 reply_outbuf(req, 0, 0);
1026 /* We special case this - as when a Windows machine
1027 is parsing a path is steps through the components
1028 one at a time - if a component fails it expects
1029 ERRbadpath, not ERRbadfile.
1031 status = map_checkpath_error(req->flags2, status);
1032 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1034 * Windows returns different error codes if
1035 * the parent directory is valid but not the
1036 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1037 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1038 * if the path is invalid.
1040 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1041 ERRDOS, ERRbadpath);
1045 reply_nterror(req, status);
1048 TALLOC_FREE(smb_fname);
1049 END_PROFILE(SMBcheckpath);
1053 /****************************************************************************
1055 ****************************************************************************/
1057 void reply_getatr(struct smb_request *req)
1059 connection_struct *conn = req->conn;
1060 struct smb_filename *smb_fname = NULL;
1067 TALLOC_CTX *ctx = talloc_tos();
1069 START_PROFILE(SMBgetatr);
1071 p = (const char *)req->buf + 1;
1072 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1073 if (!NT_STATUS_IS_OK(status)) {
1074 reply_nterror(req, status);
1078 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1079 under WfWg - weird! */
1080 if (*fname == '\0') {
1081 mode = aHIDDEN | aDIR;
1082 if (!CAN_WRITE(conn)) {
1088 status = filename_convert(ctx,
1090 req->flags2 & FLAGS2_DFS_PATHNAMES,
1094 if (!NT_STATUS_IS_OK(status)) {
1095 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1096 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1097 ERRSRV, ERRbadpath);
1100 reply_nterror(req, status);
1103 if (!VALID_STAT(smb_fname->st) &&
1104 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1105 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1106 smb_fname_str_dbg(smb_fname),
1108 reply_unixerror(req, ERRDOS,ERRbadfile);
1112 mode = dos_mode(conn, fname, &smb_fname->st);
1113 size = smb_fname->st.st_ex_size;
1114 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1120 reply_outbuf(req, 10, 0);
1122 SSVAL(req->outbuf,smb_vwv0,mode);
1123 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1124 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1126 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1128 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1130 if (Protocol >= PROTOCOL_NT1) {
1131 SSVAL(req->outbuf, smb_flg2,
1132 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1135 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1136 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1139 TALLOC_FREE(smb_fname);
1141 END_PROFILE(SMBgetatr);
1145 /****************************************************************************
1147 ****************************************************************************/
1149 void reply_setatr(struct smb_request *req)
1151 struct smb_file_time ft;
1152 connection_struct *conn = req->conn;
1153 struct smb_filename *smb_fname = NULL;
1159 TALLOC_CTX *ctx = talloc_tos();
1161 START_PROFILE(SMBsetatr);
1166 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1170 p = (const char *)req->buf + 1;
1171 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1172 if (!NT_STATUS_IS_OK(status)) {
1173 reply_nterror(req, status);
1177 status = filename_convert(ctx,
1179 req->flags2 & FLAGS2_DFS_PATHNAMES,
1183 if (!NT_STATUS_IS_OK(status)) {
1184 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1185 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1186 ERRSRV, ERRbadpath);
1189 reply_nterror(req, status);
1193 if (fname[0] == '.' && fname[1] == '\0') {
1195 * Not sure here is the right place to catch this
1196 * condition. Might be moved to somewhere else later -- vl
1198 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1202 mode = SVAL(req->vwv+0, 0);
1203 mtime = srv_make_unix_date3(req->vwv+1);
1205 ft.mtime = convert_time_t_to_timespec(mtime);
1206 status = smb_set_file_time(conn, NULL, fname,
1207 &smb_fname->st, &ft, true);
1208 if (!NT_STATUS_IS_OK(status)) {
1209 reply_unixerror(req, ERRDOS, ERRnoaccess);
1213 if (mode != FILE_ATTRIBUTE_NORMAL) {
1214 if (VALID_STAT_OF_DIR(smb_fname->st))
1219 if (file_set_dosmode(conn, fname, mode, &smb_fname->st, NULL,
1221 reply_unixerror(req, ERRDOS, ERRnoaccess);
1226 reply_outbuf(req, 0, 0);
1228 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1230 TALLOC_FREE(smb_fname);
1231 END_PROFILE(SMBsetatr);
1235 /****************************************************************************
1237 ****************************************************************************/
1239 void reply_dskattr(struct smb_request *req)
1241 connection_struct *conn = req->conn;
1242 uint64_t dfree,dsize,bsize;
1243 START_PROFILE(SMBdskattr);
1245 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1246 reply_unixerror(req, ERRHRD, ERRgeneral);
1247 END_PROFILE(SMBdskattr);
1251 reply_outbuf(req, 5, 0);
1253 if (Protocol <= PROTOCOL_LANMAN2) {
1254 double total_space, free_space;
1255 /* we need to scale this to a number that DOS6 can handle. We
1256 use floating point so we can handle large drives on systems
1257 that don't have 64 bit integers
1259 we end up displaying a maximum of 2G to DOS systems
1261 total_space = dsize * (double)bsize;
1262 free_space = dfree * (double)bsize;
1264 dsize = (uint64_t)((total_space+63*512) / (64*512));
1265 dfree = (uint64_t)((free_space+63*512) / (64*512));
1267 if (dsize > 0xFFFF) dsize = 0xFFFF;
1268 if (dfree > 0xFFFF) dfree = 0xFFFF;
1270 SSVAL(req->outbuf,smb_vwv0,dsize);
1271 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1272 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1273 SSVAL(req->outbuf,smb_vwv3,dfree);
1275 SSVAL(req->outbuf,smb_vwv0,dsize);
1276 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1277 SSVAL(req->outbuf,smb_vwv2,512);
1278 SSVAL(req->outbuf,smb_vwv3,dfree);
1281 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1283 END_PROFILE(SMBdskattr);
1288 * Utility function to split the filename from the directory.
1290 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1291 char **fname_dir_out,
1292 char **fname_mask_out)
1294 const char *p = NULL;
1295 char *fname_dir = NULL;
1296 char *fname_mask = NULL;
1298 p = strrchr_m(fname_in, '/');
1300 fname_dir = talloc_strdup(ctx, ".");
1301 fname_mask = talloc_strdup(ctx, fname_in);
1303 fname_dir = talloc_strndup(ctx, fname_in,
1304 PTR_DIFF(p, fname_in));
1305 fname_mask = talloc_strdup(ctx, p+1);
1308 if (!fname_dir || !fname_mask) {
1309 TALLOC_FREE(fname_dir);
1310 TALLOC_FREE(fname_mask);
1311 return NT_STATUS_NO_MEMORY;
1314 *fname_dir_out = fname_dir;
1315 *fname_mask_out = fname_mask;
1316 return NT_STATUS_OK;
1319 /****************************************************************************
1321 Can be called from SMBsearch, SMBffirst or SMBfunique.
1322 ****************************************************************************/
1324 void reply_search(struct smb_request *req)
1326 connection_struct *conn = req->conn;
1328 const char *mask = NULL;
1329 char *directory = NULL;
1333 struct timespec date;
1335 unsigned int numentries = 0;
1336 unsigned int maxentries = 0;
1337 bool finished = False;
1342 bool check_descend = False;
1343 bool expect_close = False;
1345 bool mask_contains_wcard = False;
1346 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1347 TALLOC_CTX *ctx = talloc_tos();
1348 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1350 START_PROFILE(SMBsearch);
1353 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1354 END_PROFILE(SMBsearch);
1358 if (lp_posix_pathnames()) {
1359 reply_unknown_new(req, req->cmd);
1360 END_PROFILE(SMBsearch);
1364 /* If we were called as SMBffirst then we must expect close. */
1365 if(req->cmd == SMBffirst) {
1366 expect_close = True;
1369 reply_outbuf(req, 1, 3);
1370 maxentries = SVAL(req->vwv+0, 0);
1371 dirtype = SVAL(req->vwv+1, 0);
1372 p = (const char *)req->buf + 1;
1373 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1374 &nt_status, &mask_contains_wcard);
1375 if (!NT_STATUS_IS_OK(nt_status)) {
1376 reply_nterror(req, nt_status);
1377 END_PROFILE(SMBsearch);
1382 status_len = SVAL(p, 0);
1385 /* dirtype &= ~aDIR; */
1387 if (status_len == 0) {
1388 struct smb_filename *smb_fname = NULL;
1390 nt_status = resolve_dfspath_wcard(ctx, conn,
1391 req->flags2 & FLAGS2_DFS_PATHNAMES,
1394 &mask_contains_wcard);
1395 if (!NT_STATUS_IS_OK(nt_status)) {
1396 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1397 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1398 ERRSRV, ERRbadpath);
1399 END_PROFILE(SMBsearch);
1402 reply_nterror(req, nt_status);
1403 END_PROFILE(SMBsearch);
1407 nt_status = unix_convert(ctx, conn, path, &smb_fname,
1408 UCF_ALLOW_WCARD_LCOMP);
1409 if (!NT_STATUS_IS_OK(nt_status)) {
1410 reply_nterror(req, nt_status);
1411 END_PROFILE(SMBsearch);
1415 nt_status = get_full_smb_filename(ctx, smb_fname, &directory);
1416 TALLOC_FREE(smb_fname);
1417 if (!NT_STATUS_IS_OK(nt_status)) {
1418 reply_nterror(req, nt_status);
1419 END_PROFILE(SMBsearch);
1423 nt_status = check_name(conn, directory);
1424 if (!NT_STATUS_IS_OK(nt_status)) {
1425 reply_nterror(req, nt_status);
1426 END_PROFILE(SMBsearch);
1430 p = strrchr_m(directory,'/');
1431 if ((p != NULL) && (*directory != '/')) {
1433 directory = talloc_strndup(ctx, directory,
1434 PTR_DIFF(p, directory));
1437 directory = talloc_strdup(ctx,".");
1441 reply_nterror(req, NT_STATUS_NO_MEMORY);
1442 END_PROFILE(SMBsearch);
1446 memset((char *)status,'\0',21);
1447 SCVAL(status,0,(dirtype & 0x1F));
1449 nt_status = dptr_create(conn,
1455 mask_contains_wcard,
1458 if (!NT_STATUS_IS_OK(nt_status)) {
1459 reply_nterror(req, nt_status);
1460 END_PROFILE(SMBsearch);
1463 dptr_num = dptr_dnum(conn->dirptr);
1467 memcpy(status,p,21);
1468 status_dirtype = CVAL(status,0) & 0x1F;
1469 if (status_dirtype != (dirtype & 0x1F)) {
1470 dirtype = status_dirtype;
1473 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1474 if (!conn->dirptr) {
1477 string_set(&conn->dirpath,dptr_path(dptr_num));
1478 mask = dptr_wcard(dptr_num);
1483 * For a 'continue' search we have no string. So
1484 * check from the initial saved string.
1486 mask_contains_wcard = ms_has_wild(mask);
1487 dirtype = dptr_attr(dptr_num);
1490 DEBUG(4,("dptr_num is %d\n",dptr_num));
1492 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1493 dptr_init_search_op(conn->dirptr);
1495 if ((dirtype&0x1F) == aVOLID) {
1496 char buf[DIR_STRUCT_SIZE];
1497 memcpy(buf,status,21);
1498 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1499 0,aVOLID,0,!allow_long_path_components)) {
1500 reply_nterror(req, NT_STATUS_NO_MEMORY);
1501 END_PROFILE(SMBsearch);
1504 dptr_fill(buf+12,dptr_num);
1505 if (dptr_zero(buf+12) && (status_len==0)) {
1510 if (message_push_blob(&req->outbuf,
1511 data_blob_const(buf, sizeof(buf)))
1513 reply_nterror(req, NT_STATUS_NO_MEMORY);
1514 END_PROFILE(SMBsearch);
1522 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1525 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1526 conn->dirpath,lp_dontdescend(SNUM(conn))));
1527 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1528 check_descend = True;
1531 for (i=numentries;(i<maxentries) && !finished;i++) {
1532 finished = !get_dir_entry(ctx,
1543 char buf[DIR_STRUCT_SIZE];
1544 memcpy(buf,status,21);
1545 if (!make_dir_struct(ctx,
1551 convert_timespec_to_time_t(date),
1552 !allow_long_path_components)) {
1553 reply_nterror(req, NT_STATUS_NO_MEMORY);
1554 END_PROFILE(SMBsearch);
1557 if (!dptr_fill(buf+12,dptr_num)) {
1560 if (message_push_blob(&req->outbuf,
1561 data_blob_const(buf, sizeof(buf)))
1563 reply_nterror(req, NT_STATUS_NO_MEMORY);
1564 END_PROFILE(SMBsearch);
1574 /* If we were called as SMBffirst with smb_search_id == NULL
1575 and no entries were found then return error and close dirptr
1578 if (numentries == 0) {
1579 dptr_close(&dptr_num);
1580 } else if(expect_close && status_len == 0) {
1581 /* Close the dptr - we know it's gone */
1582 dptr_close(&dptr_num);
1585 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1586 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1587 dptr_close(&dptr_num);
1590 if ((numentries == 0) && !mask_contains_wcard) {
1591 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1592 END_PROFILE(SMBsearch);
1596 SSVAL(req->outbuf,smb_vwv0,numentries);
1597 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1598 SCVAL(smb_buf(req->outbuf),0,5);
1599 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1601 /* The replies here are never long name. */
1602 SSVAL(req->outbuf, smb_flg2,
1603 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1604 if (!allow_long_path_components) {
1605 SSVAL(req->outbuf, smb_flg2,
1606 SVAL(req->outbuf, smb_flg2)
1607 & (~FLAGS2_LONG_PATH_COMPONENTS));
1610 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1611 SSVAL(req->outbuf, smb_flg2,
1612 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1615 directory = dptr_path(dptr_num);
1618 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1619 smb_fn_name(req->cmd),
1621 directory ? directory : "./",
1626 END_PROFILE(SMBsearch);
1630 /****************************************************************************
1631 Reply to a fclose (stop directory search).
1632 ****************************************************************************/
1634 void reply_fclose(struct smb_request *req)
1642 bool path_contains_wcard = False;
1643 TALLOC_CTX *ctx = talloc_tos();
1645 START_PROFILE(SMBfclose);
1647 if (lp_posix_pathnames()) {
1648 reply_unknown_new(req, req->cmd);
1649 END_PROFILE(SMBfclose);
1653 p = (const char *)req->buf + 1;
1654 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1655 &err, &path_contains_wcard);
1656 if (!NT_STATUS_IS_OK(err)) {
1657 reply_nterror(req, err);
1658 END_PROFILE(SMBfclose);
1662 status_len = SVAL(p,0);
1665 if (status_len == 0) {
1666 reply_doserror(req, ERRSRV, ERRsrverror);
1667 END_PROFILE(SMBfclose);
1671 memcpy(status,p,21);
1673 if(dptr_fetch(status+12,&dptr_num)) {
1674 /* Close the dptr - we know it's gone */
1675 dptr_close(&dptr_num);
1678 reply_outbuf(req, 1, 0);
1679 SSVAL(req->outbuf,smb_vwv0,0);
1681 DEBUG(3,("search close\n"));
1683 END_PROFILE(SMBfclose);
1687 /****************************************************************************
1689 ****************************************************************************/
1691 void reply_open(struct smb_request *req)
1693 connection_struct *conn = req->conn;
1694 struct smb_filename *smb_fname = NULL;
1706 uint32 create_disposition;
1707 uint32 create_options = 0;
1709 TALLOC_CTX *ctx = talloc_tos();
1711 START_PROFILE(SMBopen);
1714 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1718 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1719 deny_mode = SVAL(req->vwv+0, 0);
1720 dos_attr = SVAL(req->vwv+1, 0);
1722 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1723 STR_TERMINATE, &status);
1724 if (!NT_STATUS_IS_OK(status)) {
1725 reply_nterror(req, status);
1729 status = filename_convert(ctx,
1731 req->flags2 & FLAGS2_DFS_PATHNAMES,
1735 if (!NT_STATUS_IS_OK(status)) {
1736 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1737 reply_botherror(req,
1738 NT_STATUS_PATH_NOT_COVERED,
1739 ERRSRV, ERRbadpath);
1742 reply_nterror(req, status);
1746 if (!map_open_params_to_ntcreate(
1747 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1748 &share_mode, &create_disposition, &create_options)) {
1749 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1753 status = SMB_VFS_CREATE_FILE(
1756 0, /* root_dir_fid */
1757 smb_fname, /* fname */
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 */
1770 if (!NT_STATUS_IS_OK(status)) {
1771 if (open_was_deferred(req->mid)) {
1772 /* We have re-scheduled this call. */
1775 reply_openerror(req, status);
1779 size = smb_fname->st.st_ex_size;
1780 fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st);
1781 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1784 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1785 close_file(req, fsp, ERROR_CLOSE);
1786 reply_doserror(req, ERRDOS,ERRnoaccess);
1790 reply_outbuf(req, 7, 0);
1791 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1792 SSVAL(req->outbuf,smb_vwv1,fattr);
1793 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1794 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1796 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1798 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1799 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1801 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1802 SCVAL(req->outbuf,smb_flg,
1803 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1806 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1807 SCVAL(req->outbuf,smb_flg,
1808 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1811 TALLOC_FREE(smb_fname);
1812 END_PROFILE(SMBopen);
1816 /****************************************************************************
1817 Reply to an open and X.
1818 ****************************************************************************/
1820 void reply_open_and_X(struct smb_request *req)
1822 connection_struct *conn = req->conn;
1823 struct smb_filename *smb_fname = NULL;
1828 /* Breakout the oplock request bits so we can set the
1829 reply bits separately. */
1830 int ex_oplock_request;
1831 int core_oplock_request;
1834 int smb_sattr = SVAL(req->vwv+4, 0);
1835 uint32 smb_time = make_unix_date3(req->vwv+6);
1843 uint64_t allocation_size;
1844 ssize_t retval = -1;
1847 uint32 create_disposition;
1848 uint32 create_options = 0;
1849 TALLOC_CTX *ctx = talloc_tos();
1851 START_PROFILE(SMBopenX);
1853 if (req->wct < 15) {
1854 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1858 open_flags = SVAL(req->vwv+2, 0);
1859 deny_mode = SVAL(req->vwv+3, 0);
1860 smb_attr = SVAL(req->vwv+5, 0);
1861 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1862 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1863 oplock_request = ex_oplock_request | core_oplock_request;
1864 smb_ofun = SVAL(req->vwv+8, 0);
1865 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1867 /* If it's an IPC, pass off the pipe handler. */
1869 if (lp_nt_pipe_support()) {
1870 reply_open_pipe_and_X(conn, req);
1872 reply_doserror(req, ERRSRV, ERRaccess);
1877 /* XXXX we need to handle passed times, sattr and flags */
1878 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1879 STR_TERMINATE, &status);
1880 if (!NT_STATUS_IS_OK(status)) {
1881 reply_nterror(req, status);
1885 status = filename_convert(ctx,
1887 req->flags2 & FLAGS2_DFS_PATHNAMES,
1891 if (!NT_STATUS_IS_OK(status)) {
1892 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1893 reply_botherror(req,
1894 NT_STATUS_PATH_NOT_COVERED,
1895 ERRSRV, ERRbadpath);
1898 reply_nterror(req, status);
1902 if (!map_open_params_to_ntcreate(
1903 fname, deny_mode, smb_ofun, &access_mask,
1904 &share_mode, &create_disposition, &create_options)) {
1905 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1909 status = SMB_VFS_CREATE_FILE(
1912 0, /* root_dir_fid */
1913 smb_fname, /* fname */
1914 access_mask, /* access_mask */
1915 share_mode, /* share_access */
1916 create_disposition, /* create_disposition*/
1917 create_options, /* create_options */
1918 smb_attr, /* file_attributes */
1919 oplock_request, /* oplock_request */
1920 0, /* allocation_size */
1924 &smb_action); /* pinfo */
1926 if (!NT_STATUS_IS_OK(status)) {
1927 if (open_was_deferred(req->mid)) {
1928 /* We have re-scheduled this call. */
1931 reply_openerror(req, status);
1935 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1936 if the file is truncated or created. */
1937 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1938 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1939 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1940 close_file(req, fsp, ERROR_CLOSE);
1941 reply_nterror(req, NT_STATUS_DISK_FULL);
1944 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1946 close_file(req, fsp, ERROR_CLOSE);
1947 reply_nterror(req, NT_STATUS_DISK_FULL);
1950 smb_fname->st.st_ex_size =
1951 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1954 fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st);
1955 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1957 close_file(req, fsp, ERROR_CLOSE);
1958 reply_doserror(req, ERRDOS, ERRnoaccess);
1962 /* If the caller set the extended oplock request bit
1963 and we granted one (by whatever means) - set the
1964 correct bit for extended oplock reply.
1967 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1968 smb_action |= EXTENDED_OPLOCK_GRANTED;
1971 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1972 smb_action |= EXTENDED_OPLOCK_GRANTED;
1975 /* If the caller set the core oplock request bit
1976 and we granted one (by whatever means) - set the
1977 correct bit for core oplock reply.
1980 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1981 reply_outbuf(req, 19, 0);
1983 reply_outbuf(req, 15, 0);
1986 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1987 SCVAL(req->outbuf, smb_flg,
1988 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1991 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1992 SCVAL(req->outbuf, smb_flg,
1993 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1996 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1997 SSVAL(req->outbuf,smb_vwv3,fattr);
1998 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1999 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2001 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2003 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2004 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2005 SSVAL(req->outbuf,smb_vwv11,smb_action);
2007 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2008 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2013 TALLOC_FREE(smb_fname);
2014 END_PROFILE(SMBopenX);
2018 /****************************************************************************
2019 Reply to a SMBulogoffX.
2020 ****************************************************************************/
2022 void reply_ulogoffX(struct smb_request *req)
2024 struct smbd_server_connection *sconn = smbd_server_conn;
2027 START_PROFILE(SMBulogoffX);
2029 vuser = get_valid_user_struct(sconn, req->vuid);
2032 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2036 /* in user level security we are supposed to close any files
2037 open by this user */
2038 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2039 file_close_user(req->vuid);
2042 invalidate_vuid(sconn, req->vuid);
2044 reply_outbuf(req, 2, 0);
2046 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2048 END_PROFILE(SMBulogoffX);
2052 /****************************************************************************
2053 Reply to a mknew or a create.
2054 ****************************************************************************/
2056 void reply_mknew(struct smb_request *req)
2058 connection_struct *conn = req->conn;
2059 struct smb_filename *smb_fname = NULL;
2062 struct smb_file_time ft;
2064 int oplock_request = 0;
2066 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2067 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2068 uint32 create_disposition;
2069 uint32 create_options = 0;
2070 TALLOC_CTX *ctx = talloc_tos();
2072 START_PROFILE(SMBcreate);
2076 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2080 fattr = SVAL(req->vwv+0, 0);
2081 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2084 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2086 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2087 STR_TERMINATE, &status);
2088 if (!NT_STATUS_IS_OK(status)) {
2089 reply_nterror(req, status);
2093 status = filename_convert(ctx,
2095 req->flags2 & FLAGS2_DFS_PATHNAMES,
2099 if (!NT_STATUS_IS_OK(status)) {
2100 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2101 reply_botherror(req,
2102 NT_STATUS_PATH_NOT_COVERED,
2103 ERRSRV, ERRbadpath);
2106 reply_nterror(req, status);
2110 if (fattr & aVOLID) {
2111 DEBUG(0,("Attempt to create file (%s) with volid set - "
2112 "please report this\n", fname));
2115 if(req->cmd == SMBmknew) {
2116 /* We should fail if file exists. */
2117 create_disposition = FILE_CREATE;
2119 /* Create if file doesn't exist, truncate if it does. */
2120 create_disposition = FILE_OVERWRITE_IF;
2123 status = SMB_VFS_CREATE_FILE(
2126 0, /* root_dir_fid */
2127 smb_fname, /* fname */
2128 access_mask, /* access_mask */
2129 share_mode, /* share_access */
2130 create_disposition, /* create_disposition*/
2131 create_options, /* create_options */
2132 fattr, /* file_attributes */
2133 oplock_request, /* oplock_request */
2134 0, /* allocation_size */
2140 if (!NT_STATUS_IS_OK(status)) {
2141 if (open_was_deferred(req->mid)) {
2142 /* We have re-scheduled this call. */
2145 reply_openerror(req, status);
2149 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2150 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &smb_fname->st,
2152 if (!NT_STATUS_IS_OK(status)) {
2153 END_PROFILE(SMBcreate);
2157 reply_outbuf(req, 1, 0);
2158 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2160 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2161 SCVAL(req->outbuf,smb_flg,
2162 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2165 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2166 SCVAL(req->outbuf,smb_flg,
2167 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2170 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2171 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2172 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2175 TALLOC_FREE(smb_fname);
2176 END_PROFILE(SMBcreate);
2180 /****************************************************************************
2181 Reply to a create temporary file.
2182 ****************************************************************************/
2184 void reply_ctemp(struct smb_request *req)
2186 connection_struct *conn = req->conn;
2187 struct smb_filename *smb_fname = NULL;
2195 TALLOC_CTX *ctx = talloc_tos();
2197 START_PROFILE(SMBctemp);
2200 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2204 fattr = SVAL(req->vwv+0, 0);
2205 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2207 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2208 STR_TERMINATE, &status);
2209 if (!NT_STATUS_IS_OK(status)) {
2210 reply_nterror(req, status);
2214 fname = talloc_asprintf(ctx,
2218 fname = talloc_strdup(ctx, "TMXXXXXX");
2222 reply_nterror(req, NT_STATUS_NO_MEMORY);
2226 status = filename_convert(ctx, conn,
2227 req->flags2 & FLAGS2_DFS_PATHNAMES,
2231 if (!NT_STATUS_IS_OK(status)) {
2232 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2233 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2234 ERRSRV, ERRbadpath);
2237 reply_nterror(req, status);
2241 tmpfd = mkstemp(smb_fname->base_name);
2243 reply_unixerror(req, ERRDOS, ERRnoaccess);
2247 SMB_VFS_STAT(conn, smb_fname);
2249 /* We should fail if file does not exist. */
2250 status = SMB_VFS_CREATE_FILE(
2253 0, /* root_dir_fid */
2254 smb_fname, /* fname */
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 */
2267 /* close fd from mkstemp() */
2270 if (!NT_STATUS_IS_OK(status)) {
2271 if (open_was_deferred(req->mid)) {
2272 /* We have re-scheduled this call. */
2275 reply_openerror(req, status);
2279 reply_outbuf(req, 1, 0);
2280 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2282 /* the returned filename is relative to the directory */
2283 s = strrchr_m(fsp->fsp_name, '/');
2291 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2292 thing in the byte section. JRA */
2293 SSVALS(p, 0, -1); /* what is this? not in spec */
2295 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2297 reply_nterror(req, NT_STATUS_NO_MEMORY);
2301 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2302 SCVAL(req->outbuf, smb_flg,
2303 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2306 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2307 SCVAL(req->outbuf, smb_flg,
2308 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2311 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2312 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2313 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2315 TALLOC_FREE(smb_fname);
2316 END_PROFILE(SMBctemp);
2320 /*******************************************************************
2321 Check if a user is allowed to rename a file.
2322 ********************************************************************/
2324 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2325 uint16 dirtype, SMB_STRUCT_STAT *pst)
2329 if (!CAN_WRITE(conn)) {
2330 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2333 fmode = dos_mode(conn, fsp->fsp_name, pst);
2334 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2335 return NT_STATUS_NO_SUCH_FILE;
2338 if (S_ISDIR(pst->st_ex_mode)) {
2339 if (fsp->posix_open) {
2340 return NT_STATUS_OK;
2343 /* If no pathnames are open below this
2344 directory, allow the rename. */
2346 if (file_find_subpath(fsp)) {
2347 return NT_STATUS_ACCESS_DENIED;
2349 return NT_STATUS_OK;
2352 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2353 return NT_STATUS_OK;
2356 return NT_STATUS_ACCESS_DENIED;
2359 /*******************************************************************
2360 * unlink a file with all relevant access checks
2361 *******************************************************************/
2363 static NTSTATUS do_unlink(connection_struct *conn,
2364 struct smb_request *req,
2365 struct smb_filename *smb_fname,
2371 uint32 dirtype_orig = dirtype;
2374 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2376 if (!CAN_WRITE(conn)) {
2377 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2380 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
2381 return map_nt_error_from_unix(errno);
2384 status = get_full_smb_filename(smb_fname, smb_fname, &fname);
2385 if (!NT_STATUS_IS_OK(status)) {
2388 fattr = dos_mode(conn, fname, &smb_fname->st);
2391 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2392 dirtype = aDIR|aARCH|aRONLY;
2395 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2397 return NT_STATUS_NO_SUCH_FILE;
2400 if (!dir_check_ftype(conn, fattr, dirtype)) {
2402 return NT_STATUS_FILE_IS_A_DIRECTORY;
2404 return NT_STATUS_NO_SUCH_FILE;
2407 if (dirtype_orig & 0x8000) {
2408 /* These will never be set for POSIX. */
2409 return NT_STATUS_NO_SUCH_FILE;
2413 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2414 return NT_STATUS_FILE_IS_A_DIRECTORY;
2417 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2418 return NT_STATUS_NO_SUCH_FILE;
2421 if (dirtype & 0xFF00) {
2422 /* These will never be set for POSIX. */
2423 return NT_STATUS_NO_SUCH_FILE;
2428 return NT_STATUS_NO_SUCH_FILE;
2431 /* Can't delete a directory. */
2433 return NT_STATUS_FILE_IS_A_DIRECTORY;
2438 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2439 return NT_STATUS_OBJECT_NAME_INVALID;
2440 #endif /* JRATEST */
2442 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2444 On a Windows share, a file with read-only dosmode can be opened with
2445 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2446 fails with NT_STATUS_CANNOT_DELETE error.
2448 This semantic causes a problem that a user can not
2449 rename a file with read-only dosmode on a Samba share
2450 from a Windows command prompt (i.e. cmd.exe, but can rename
2451 from Windows Explorer).
2454 if (!lp_delete_readonly(SNUM(conn))) {
2455 if (fattr & aRONLY) {
2456 return NT_STATUS_CANNOT_DELETE;
2460 /* On open checks the open itself will check the share mode, so
2461 don't do it here as we'll get it wrong. */
2463 status = SMB_VFS_CREATE_FILE
2466 0, /* root_dir_fid */
2467 smb_fname, /* fname */
2468 DELETE_ACCESS, /* access_mask */
2469 FILE_SHARE_NONE, /* share_access */
2470 FILE_OPEN, /* create_disposition*/
2471 FILE_NON_DIRECTORY_FILE, /* create_options */
2472 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2473 0, /* oplock_request */
2474 0, /* allocation_size */
2480 if (!NT_STATUS_IS_OK(status)) {
2481 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2482 nt_errstr(status)));
2486 /* The set is across all open files on this dev/inode pair. */
2487 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2488 close_file(req, fsp, NORMAL_CLOSE);
2489 return NT_STATUS_ACCESS_DENIED;
2492 return close_file(req, fsp, NORMAL_CLOSE);
2495 /****************************************************************************
2496 The guts of the unlink command, split out so it may be called by the NT SMB
2498 ****************************************************************************/
2500 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2501 uint32 dirtype, const char *name_in, bool has_wild)
2503 struct smb_filename *smb_fname = NULL;
2504 char *fname_dir = NULL;
2505 char *fname_mask = NULL;
2507 NTSTATUS status = NT_STATUS_OK;
2508 TALLOC_CTX *ctx = talloc_tos();
2510 status = unix_convert(ctx, conn, name_in, &smb_fname,
2511 has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
2512 if (!NT_STATUS_IS_OK(status)) {
2516 /* Split up the directory from the filename/mask. */
2517 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2518 &fname_dir, &fname_mask);
2519 if (!NT_STATUS_IS_OK(status)) {
2524 * We should only check the mangled cache
2525 * here if unix_convert failed. This means
2526 * that the path in 'mask' doesn't exist
2527 * on the file system and so we need to look
2528 * for a possible mangle. This patch from
2529 * Tine Smukavec <valentin.smukavec@hermes.si>.
2532 if (!VALID_STAT(smb_fname->st) &&
2533 mangle_is_mangled(fname_mask, conn->params)) {
2534 char *new_mask = NULL;
2535 mangle_lookup_name_from_8_3(ctx, fname_mask,
2536 &new_mask, conn->params);
2538 TALLOC_FREE(fname_mask);
2539 fname_mask = new_mask;
2546 * Only one file needs to be unlinked. Append the mask back
2547 * onto the directory.
2549 TALLOC_FREE(smb_fname->base_name);
2550 smb_fname->base_name = talloc_asprintf(smb_fname,
2554 if (!smb_fname->base_name) {
2555 status = NT_STATUS_NO_MEMORY;
2559 dirtype = FILE_ATTRIBUTE_NORMAL;
2562 status = check_name(conn, smb_fname->base_name);
2563 if (!NT_STATUS_IS_OK(status)) {
2567 status = do_unlink(conn, req, smb_fname, dirtype);
2568 if (!NT_STATUS_IS_OK(status)) {
2574 struct smb_Dir *dir_hnd = NULL;
2578 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2579 status = NT_STATUS_OBJECT_NAME_INVALID;
2583 if (strequal(fname_mask,"????????.???")) {
2584 TALLOC_FREE(fname_mask);
2585 fname_mask = talloc_strdup(ctx, "*");
2587 status = NT_STATUS_NO_MEMORY;
2592 status = check_name(conn, fname_dir);
2593 if (!NT_STATUS_IS_OK(status)) {
2597 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2599 if (dir_hnd == NULL) {
2600 status = map_nt_error_from_unix(errno);
2604 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2605 the pattern matches against the long name, otherwise the short name
2606 We don't implement this yet XXXX
2609 status = NT_STATUS_NO_SUCH_FILE;
2611 while ((dname = ReadDirName(dir_hnd, &offset,
2613 if (!is_visible_file(conn, fname_dir, dname,
2614 &smb_fname->st, true)) {
2618 /* Quick check for "." and ".." */
2619 if (ISDOT(dname) || ISDOTDOT(dname)) {
2623 if(!mask_match(dname, fname_mask,
2624 conn->case_sensitive)) {
2628 TALLOC_FREE(smb_fname->base_name);
2629 smb_fname->base_name =
2630 talloc_asprintf(smb_fname, "%s/%s",
2633 if (!smb_fname->base_name) {
2634 TALLOC_FREE(dir_hnd);
2635 status = NT_STATUS_NO_MEMORY;
2639 status = check_name(conn, smb_fname->base_name);
2640 if (!NT_STATUS_IS_OK(status)) {
2641 TALLOC_FREE(dir_hnd);
2645 status = do_unlink(conn, req, smb_fname, dirtype);
2646 if (!NT_STATUS_IS_OK(status)) {
2651 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2652 smb_fname->base_name));
2654 TALLOC_FREE(dir_hnd);
2657 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2658 status = map_nt_error_from_unix(errno);
2662 TALLOC_FREE(smb_fname);
2663 TALLOC_FREE(fname_dir);
2664 TALLOC_FREE(fname_mask);
2668 /****************************************************************************
2670 ****************************************************************************/
2672 void reply_unlink(struct smb_request *req)
2674 connection_struct *conn = req->conn;
2678 bool path_contains_wcard = False;
2679 TALLOC_CTX *ctx = talloc_tos();
2681 START_PROFILE(SMBunlink);
2684 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2685 END_PROFILE(SMBunlink);
2689 dirtype = SVAL(req->vwv+0, 0);
2691 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2692 STR_TERMINATE, &status,
2693 &path_contains_wcard);
2694 if (!NT_STATUS_IS_OK(status)) {
2695 reply_nterror(req, status);
2696 END_PROFILE(SMBunlink);
2700 status = resolve_dfspath_wcard(ctx, conn,
2701 req->flags2 & FLAGS2_DFS_PATHNAMES,
2704 &path_contains_wcard);
2705 if (!NT_STATUS_IS_OK(status)) {
2706 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2707 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2708 ERRSRV, ERRbadpath);
2709 END_PROFILE(SMBunlink);
2712 reply_nterror(req, status);
2713 END_PROFILE(SMBunlink);
2717 DEBUG(3,("reply_unlink : %s\n",name));
2719 status = unlink_internals(conn, req, dirtype, name,
2720 path_contains_wcard);
2721 if (!NT_STATUS_IS_OK(status)) {
2722 if (open_was_deferred(req->mid)) {
2723 /* We have re-scheduled this call. */
2724 END_PROFILE(SMBunlink);
2727 reply_nterror(req, status);
2728 END_PROFILE(SMBunlink);
2732 reply_outbuf(req, 0, 0);
2733 END_PROFILE(SMBunlink);
2738 /****************************************************************************
2740 ****************************************************************************/
2742 static void fail_readraw(void)
2744 const char *errstr = talloc_asprintf(talloc_tos(),
2745 "FAIL ! reply_readbraw: socket write fail (%s)",
2750 exit_server_cleanly(errstr);
2753 /****************************************************************************
2754 Fake (read/write) sendfile. Returns -1 on read or write fail.
2755 ****************************************************************************/
2757 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2761 size_t tosend = nread;
2768 bufsize = MIN(nread, 65536);
2770 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2774 while (tosend > 0) {
2778 if (tosend > bufsize) {
2783 ret = read_file(fsp,buf,startpos,cur_read);
2789 /* If we had a short read, fill with zeros. */
2790 if (ret < cur_read) {
2791 memset(buf + ret, '\0', cur_read - ret);
2794 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2799 startpos += cur_read;
2803 return (ssize_t)nread;
2806 #if defined(WITH_SENDFILE)
2807 /****************************************************************************
2808 Deal with the case of sendfile reading less bytes from the file than
2809 requested. Fill with zeros (all we can do).
2810 ****************************************************************************/
2812 static void sendfile_short_send(files_struct *fsp,
2817 #define SHORT_SEND_BUFSIZE 1024
2818 if (nread < headersize) {
2819 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2820 "header for file %s (%s). Terminating\n",
2821 fsp->fsp_name, strerror(errno) ));
2822 exit_server_cleanly("sendfile_short_send failed");
2825 nread -= headersize;
2827 if (nread < smb_maxcnt) {
2828 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2830 exit_server_cleanly("sendfile_short_send: "
2834 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2835 "with zeros !\n", fsp->fsp_name));
2837 while (nread < smb_maxcnt) {
2839 * We asked for the real file size and told sendfile
2840 * to not go beyond the end of the file. But it can
2841 * happen that in between our fstat call and the
2842 * sendfile call the file was truncated. This is very
2843 * bad because we have already announced the larger
2844 * number of bytes to the client.
2846 * The best we can do now is to send 0-bytes, just as
2847 * a read from a hole in a sparse file would do.
2849 * This should happen rarely enough that I don't care
2850 * about efficiency here :-)
2854 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2855 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2856 exit_server_cleanly("sendfile_short_send: "
2857 "write_data failed");
2864 #endif /* defined WITH_SENDFILE */
2866 /****************************************************************************
2867 Return a readbraw error (4 bytes of zero).
2868 ****************************************************************************/
2870 static void reply_readbraw_error(void)
2874 if (write_data(smbd_server_fd(),header,4) != 4) {
2879 /****************************************************************************
2880 Use sendfile in readbraw.
2881 ****************************************************************************/
2883 static void send_file_readbraw(connection_struct *conn,
2884 struct smb_request *req,
2890 char *outbuf = NULL;
2893 #if defined(WITH_SENDFILE)
2895 * We can only use sendfile on a non-chained packet
2896 * but we can use on a non-oplocked file. tridge proved this
2897 * on a train in Germany :-). JRA.
2898 * reply_readbraw has already checked the length.
2901 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2902 (fsp->wcp == NULL) &&
2903 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2904 ssize_t sendfile_read = -1;
2906 DATA_BLOB header_blob;
2908 _smb_setlen(header,nread);
2909 header_blob = data_blob_const(header, 4);
2911 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2912 &header_blob, startpos, nread)) == -1) {
2913 /* Returning ENOSYS means no data at all was sent.
2914 * Do this as a normal read. */
2915 if (errno == ENOSYS) {
2916 goto normal_readbraw;
2920 * Special hack for broken Linux with no working sendfile. If we
2921 * return EINTR we sent the header but not the rest of the data.
2922 * Fake this up by doing read/write calls.
2924 if (errno == EINTR) {
2925 /* Ensure we don't do this again. */
2926 set_use_sendfile(SNUM(conn), False);
2927 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2929 if (fake_sendfile(fsp, startpos, nread) == -1) {
2930 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2931 fsp->fsp_name, strerror(errno) ));
2932 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2937 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2938 fsp->fsp_name, strerror(errno) ));
2939 exit_server_cleanly("send_file_readbraw sendfile failed");
2940 } else if (sendfile_read == 0) {
2942 * Some sendfile implementations return 0 to indicate
2943 * that there was a short read, but nothing was
2944 * actually written to the socket. In this case,
2945 * fallback to the normal read path so the header gets
2946 * the correct byte count.
2948 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2949 "bytes falling back to the normal read: "
2950 "%s\n", fsp->fsp_name));
2951 goto normal_readbraw;
2954 /* Deal with possible short send. */
2955 if (sendfile_read != 4+nread) {
2956 sendfile_short_send(fsp, sendfile_read, 4, nread);
2964 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2966 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2967 (unsigned)(nread+4)));
2968 reply_readbraw_error();
2973 ret = read_file(fsp,outbuf+4,startpos,nread);
2974 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2983 _smb_setlen(outbuf,ret);
2984 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2987 TALLOC_FREE(outbuf);
2990 /****************************************************************************
2991 Reply to a readbraw (core+ protocol).
2992 ****************************************************************************/
2994 void reply_readbraw(struct smb_request *req)
2996 connection_struct *conn = req->conn;
2997 ssize_t maxcount,mincount;
3001 struct lock_struct lock;
3005 START_PROFILE(SMBreadbraw);
3007 if (srv_is_signing_active(smbd_server_conn) ||
3008 is_encrypted_packet(req->inbuf)) {
3009 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3010 "raw reads/writes are disallowed.");
3014 reply_readbraw_error();
3015 END_PROFILE(SMBreadbraw);
3020 * Special check if an oplock break has been issued
3021 * and the readraw request croses on the wire, we must
3022 * return a zero length response here.
3025 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3028 * We have to do a check_fsp by hand here, as
3029 * we must always return 4 zero bytes on error,
3033 if (!fsp || !conn || conn != fsp->conn ||
3034 req->vuid != fsp->vuid ||
3035 fsp->is_directory || fsp->fh->fd == -1) {
3037 * fsp could be NULL here so use the value from the packet. JRA.
3039 DEBUG(3,("reply_readbraw: fnum %d not valid "
3041 (int)SVAL(req->vwv+0, 0)));
3042 reply_readbraw_error();
3043 END_PROFILE(SMBreadbraw);
3047 /* Do a "by hand" version of CHECK_READ. */
3048 if (!(fsp->can_read ||
3049 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3050 (fsp->access_mask & FILE_EXECUTE)))) {
3051 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3052 (int)SVAL(req->vwv+0, 0)));
3053 reply_readbraw_error();
3054 END_PROFILE(SMBreadbraw);
3058 flush_write_cache(fsp, READRAW_FLUSH);
3060 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3061 if(req->wct == 10) {
3063 * This is a large offset (64 bit) read.
3065 #ifdef LARGE_SMB_OFF_T
3067 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3069 #else /* !LARGE_SMB_OFF_T */
3072 * Ensure we haven't been sent a >32 bit offset.
3075 if(IVAL(req->vwv+8, 0) != 0) {
3076 DEBUG(0,("reply_readbraw: large offset "
3077 "(%x << 32) used and we don't support "
3078 "64 bit offsets.\n",
3079 (unsigned int)IVAL(req->vwv+8, 0) ));
3080 reply_readbraw_error();
3081 END_PROFILE(SMBreadbraw);
3085 #endif /* LARGE_SMB_OFF_T */
3088 DEBUG(0,("reply_readbraw: negative 64 bit "
3089 "readraw offset (%.0f) !\n",
3090 (double)startpos ));
3091 reply_readbraw_error();
3092 END_PROFILE(SMBreadbraw);
3097 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3098 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3100 /* ensure we don't overrun the packet size */
3101 maxcount = MIN(65535,maxcount);
3103 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3104 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3107 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3108 reply_readbraw_error();
3109 END_PROFILE(SMBreadbraw);
3113 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3114 size = st.st_ex_size;
3117 if (startpos >= size) {
3120 nread = MIN(maxcount,(size - startpos));
3123 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3124 if (nread < mincount)
3128 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3129 "min=%lu nread=%lu\n",
3130 fsp->fnum, (double)startpos,
3131 (unsigned long)maxcount,
3132 (unsigned long)mincount,
3133 (unsigned long)nread ) );
3135 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3137 DEBUG(5,("reply_readbraw finished\n"));
3139 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3141 END_PROFILE(SMBreadbraw);
3146 #define DBGC_CLASS DBGC_LOCKING
3148 /****************************************************************************
3149 Reply to a lockread (core+ protocol).
3150 ****************************************************************************/
3152 void reply_lockread(struct smb_request *req)
3154 connection_struct *conn = req->conn;
3161 struct byte_range_lock *br_lck = NULL;
3163 struct smbd_server_connection *sconn = smbd_server_conn;
3165 START_PROFILE(SMBlockread);
3168 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3169 END_PROFILE(SMBlockread);
3173 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3175 if (!check_fsp(conn, req, fsp)) {
3176 END_PROFILE(SMBlockread);
3180 if (!CHECK_READ(fsp,req)) {
3181 reply_doserror(req, ERRDOS, ERRbadaccess);
3182 END_PROFILE(SMBlockread);
3186 numtoread = SVAL(req->vwv+1, 0);
3187 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3189 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3191 reply_outbuf(req, 5, numtoread + 3);
3193 data = smb_buf(req->outbuf) + 3;
3196 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3197 * protocol request that predates the read/write lock concept.
3198 * Thus instead of asking for a read lock here we need to ask
3199 * for a write lock. JRA.
3200 * Note that the requested lock size is unaffected by max_recv.
3203 br_lck = do_lock(smbd_messaging_context(),
3206 (uint64_t)numtoread,
3210 False, /* Non-blocking lock. */
3214 TALLOC_FREE(br_lck);
3216 if (NT_STATUS_V(status)) {
3217 reply_nterror(req, status);
3218 END_PROFILE(SMBlockread);
3223 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3226 if (numtoread > sconn->smb1.negprot.max_recv) {
3227 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3228 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3229 (unsigned int)numtoread,
3230 (unsigned int)sconn->smb1.negprot.max_recv));
3231 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3233 nread = read_file(fsp,data,startpos,numtoread);
3236 reply_unixerror(req, ERRDOS, ERRnoaccess);
3237 END_PROFILE(SMBlockread);
3241 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3243 SSVAL(req->outbuf,smb_vwv0,nread);
3244 SSVAL(req->outbuf,smb_vwv5,nread+3);
3245 p = smb_buf(req->outbuf);
3246 SCVAL(p,0,0); /* pad byte. */
3249 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3250 fsp->fnum, (int)numtoread, (int)nread));
3252 END_PROFILE(SMBlockread);
3257 #define DBGC_CLASS DBGC_ALL
3259 /****************************************************************************
3261 ****************************************************************************/
3263 void reply_read(struct smb_request *req)
3265 connection_struct *conn = req->conn;
3272 struct lock_struct lock;
3273 struct smbd_server_connection *sconn = smbd_server_conn;
3275 START_PROFILE(SMBread);
3278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3279 END_PROFILE(SMBread);
3283 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3285 if (!check_fsp(conn, req, fsp)) {
3286 END_PROFILE(SMBread);
3290 if (!CHECK_READ(fsp,req)) {
3291 reply_doserror(req, ERRDOS, ERRbadaccess);
3292 END_PROFILE(SMBread);
3296 numtoread = SVAL(req->vwv+1, 0);
3297 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3299 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3302 * The requested read size cannot be greater than max_recv. JRA.
3304 if (numtoread > sconn->smb1.negprot.max_recv) {
3305 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3306 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3307 (unsigned int)numtoread,
3308 (unsigned int)sconn->smb1.negprot.max_recv));
3309 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3312 reply_outbuf(req, 5, numtoread+3);
3314 data = smb_buf(req->outbuf) + 3;
3316 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3317 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3320 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3321 reply_doserror(req, ERRDOS,ERRlock);
3322 END_PROFILE(SMBread);
3327 nread = read_file(fsp,data,startpos,numtoread);
3330 reply_unixerror(req, ERRDOS,ERRnoaccess);
3334 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3336 SSVAL(req->outbuf,smb_vwv0,nread);
3337 SSVAL(req->outbuf,smb_vwv5,nread+3);
3338 SCVAL(smb_buf(req->outbuf),0,1);
3339 SSVAL(smb_buf(req->outbuf),1,nread);
3341 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3342 fsp->fnum, (int)numtoread, (int)nread ) );
3345 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3347 END_PROFILE(SMBread);
3351 /****************************************************************************
3353 ****************************************************************************/
3355 static int setup_readX_header(struct smb_request *req, char *outbuf,
3361 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3362 data = smb_buf(outbuf);
3364 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3366 SCVAL(outbuf,smb_vwv0,0xFF);
3367 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3368 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3369 SSVAL(outbuf,smb_vwv6,
3371 + 1 /* the wct field */
3372 + 12 * sizeof(uint16_t) /* vwv */
3373 + 2); /* the buflen field */
3374 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3375 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3376 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3377 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3381 /****************************************************************************
3382 Reply to a read and X - possibly using sendfile.
3383 ****************************************************************************/
3385 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3386 files_struct *fsp, SMB_OFF_T startpos,
3389 SMB_STRUCT_STAT sbuf;
3391 struct lock_struct lock;
3393 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3394 reply_unixerror(req, ERRDOS, ERRnoaccess);
3398 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3399 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3402 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3403 reply_doserror(req, ERRDOS, ERRlock);
3407 if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
3408 || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
3410 * We already know that we would do a short read, so don't
3411 * try the sendfile() path.
3413 goto nosendfile_read;
3416 #if defined(WITH_SENDFILE)
3418 * We can only use sendfile on a non-chained packet
3419 * but we can use on a non-oplocked file. tridge proved this
3420 * on a train in Germany :-). JRA.
3423 if (!req_is_in_chain(req) &&
3424 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3425 (fsp->wcp == NULL) &&
3426 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3427 uint8 headerbuf[smb_size + 12 * 2];
3431 * Set up the packet header before send. We
3432 * assume here the sendfile will work (get the
3433 * correct amount of data).
3436 header = data_blob_const(headerbuf, sizeof(headerbuf));
3438 construct_reply_common_req(req, (char *)headerbuf);
3439 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3441 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3442 /* Returning ENOSYS means no data at all was sent.
3443 Do this as a normal read. */
3444 if (errno == ENOSYS) {
3449 * Special hack for broken Linux with no working sendfile. If we
3450 * return EINTR we sent the header but not the rest of the data.
3451 * Fake this up by doing read/write calls.
3454 if (errno == EINTR) {
3455 /* Ensure we don't do this again. */
3456 set_use_sendfile(SNUM(conn), False);
3457 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3458 nread = fake_sendfile(fsp, startpos,
3461 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3462 fsp->fsp_name, strerror(errno) ));
3463 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3465 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3466 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3467 /* No outbuf here means successful sendfile. */
3471 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3472 fsp->fsp_name, strerror(errno) ));
3473 exit_server_cleanly("send_file_readX sendfile failed");
3474 } else if (nread == 0) {
3476 * Some sendfile implementations return 0 to indicate
3477 * that there was a short read, but nothing was
3478 * actually written to the socket. In this case,
3479 * fallback to the normal read path so the header gets
3480 * the correct byte count.
3482 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3483 "falling back to the normal read: %s\n",
3488 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3489 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3491 /* Deal with possible short send. */
3492 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3493 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3495 /* No outbuf here means successful sendfile. */
3496 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3497 SMB_PERFCOUNT_END(&req->pcd);
3505 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3506 uint8 headerbuf[smb_size + 2*12];
3508 construct_reply_common_req(req, (char *)headerbuf);
3509 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3511 /* Send out the header. */
3512 if (write_data(smbd_server_fd(), (char *)headerbuf,
3513 sizeof(headerbuf)) != sizeof(headerbuf)) {
3514 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3515 fsp->fsp_name, strerror(errno) ));
3516 exit_server_cleanly("send_file_readX sendfile failed");
3518 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3520 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3521 fsp->fsp_name, strerror(errno) ));
3522 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3529 reply_outbuf(req, 12, smb_maxcnt);
3531 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3533 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3536 reply_unixerror(req, ERRDOS, ERRnoaccess);
3540 setup_readX_header(req, (char *)req->outbuf, nread);
3542 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3543 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3549 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3550 TALLOC_FREE(req->outbuf);
3554 /****************************************************************************
3555 Reply to a read and X.
3556 ****************************************************************************/
3558 void reply_read_and_X(struct smb_request *req)
3560 connection_struct *conn = req->conn;
3564 bool big_readX = False;
3566 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3569 START_PROFILE(SMBreadX);
3571 if ((req->wct != 10) && (req->wct != 12)) {
3572 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3576 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3577 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3578 smb_maxcnt = SVAL(req->vwv+5, 0);
3580 /* If it's an IPC, pass off the pipe handler. */
3582 reply_pipe_read_and_X(req);
3583 END_PROFILE(SMBreadX);
3587 if (!check_fsp(conn, req, fsp)) {
3588 END_PROFILE(SMBreadX);
3592 if (!CHECK_READ(fsp,req)) {
3593 reply_doserror(req, ERRDOS,ERRbadaccess);
3594 END_PROFILE(SMBreadX);
3598 if (global_client_caps & CAP_LARGE_READX) {
3599 size_t upper_size = SVAL(req->vwv+7, 0);
3600 smb_maxcnt |= (upper_size<<16);
3601 if (upper_size > 1) {
3602 /* Can't do this on a chained packet. */
3603 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3604 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3605 END_PROFILE(SMBreadX);
3608 /* We currently don't do this on signed or sealed data. */
3609 if (srv_is_signing_active(smbd_server_conn) ||
3610 is_encrypted_packet(req->inbuf)) {
3611 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3612 END_PROFILE(SMBreadX);
3615 /* Is there room in the reply for this data ? */
3616 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3618 NT_STATUS_INVALID_PARAMETER);
3619 END_PROFILE(SMBreadX);
3626 if (req->wct == 12) {
3627 #ifdef LARGE_SMB_OFF_T
3629 * This is a large offset (64 bit) read.
3631 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3633 #else /* !LARGE_SMB_OFF_T */
3636 * Ensure we haven't been sent a >32 bit offset.
3639 if(IVAL(req->vwv+10, 0) != 0) {
3640 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3641 "used and we don't support 64 bit offsets.\n",
3642 (unsigned int)IVAL(req->vwv+10, 0) ));
3643 END_PROFILE(SMBreadX);
3644 reply_doserror(req, ERRDOS, ERRbadaccess);
3648 #endif /* LARGE_SMB_OFF_T */
3653 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3657 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3660 END_PROFILE(SMBreadX);
3664 /****************************************************************************
3665 Error replies to writebraw must have smb_wct == 1. Fix this up.
3666 ****************************************************************************/
3668 void error_to_writebrawerr(struct smb_request *req)
3670 uint8 *old_outbuf = req->outbuf;
3672 reply_outbuf(req, 1, 0);
3674 memcpy(req->outbuf, old_outbuf, smb_size);
3675 TALLOC_FREE(old_outbuf);
3678 /****************************************************************************
3679 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3680 ****************************************************************************/
3682 void reply_writebraw(struct smb_request *req)
3684 connection_struct *conn = req->conn;
3687 ssize_t total_written=0;
3688 size_t numtowrite=0;
3694 struct lock_struct lock;
3697 START_PROFILE(SMBwritebraw);
3700 * If we ever reply with an error, it must have the SMB command
3701 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3704 SCVAL(req->inbuf,smb_com,SMBwritec);
3706 if (srv_is_signing_active(smbd_server_conn)) {
3707 END_PROFILE(SMBwritebraw);
3708 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3709 "raw reads/writes are disallowed.");
3712 if (req->wct < 12) {
3713 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3714 error_to_writebrawerr(req);
3715 END_PROFILE(SMBwritebraw);
3719 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3720 if (!check_fsp(conn, req, fsp)) {
3721 error_to_writebrawerr(req);
3722 END_PROFILE(SMBwritebraw);
3726 if (!CHECK_WRITE(fsp)) {
3727 reply_doserror(req, ERRDOS, ERRbadaccess);
3728 error_to_writebrawerr(req);
3729 END_PROFILE(SMBwritebraw);
3733 tcount = IVAL(req->vwv+1, 0);
3734 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3735 write_through = BITSETW(req->vwv+7,0);
3737 /* We have to deal with slightly different formats depending
3738 on whether we are using the core+ or lanman1.0 protocol */
3740 if(Protocol <= PROTOCOL_COREPLUS) {
3741 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3742 data = smb_buf(req->inbuf);
3744 numtowrite = SVAL(req->vwv+10, 0);
3745 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3748 /* Ensure we don't write bytes past the end of this packet. */
3749 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3751 error_to_writebrawerr(req);
3752 END_PROFILE(SMBwritebraw);
3756 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3757 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3760 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3761 reply_doserror(req, ERRDOS, ERRlock);
3762 error_to_writebrawerr(req);
3763 END_PROFILE(SMBwritebraw);
3768 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3771 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3772 "wrote=%d sync=%d\n",
3773 fsp->fnum, (double)startpos, (int)numtowrite,
3774 (int)nwritten, (int)write_through));
3776 if (nwritten < (ssize_t)numtowrite) {
3777 reply_unixerror(req, ERRHRD, ERRdiskfull);
3778 error_to_writebrawerr(req);
3782 total_written = nwritten;
3784 /* Allocate a buffer of 64k + length. */
3785 buf = TALLOC_ARRAY(NULL, char, 65540);
3787 reply_doserror(req, ERRDOS, ERRnomem);
3788 error_to_writebrawerr(req);
3792 /* Return a SMBwritebraw message to the redirector to tell
3793 * it to send more bytes */
3795 memcpy(buf, req->inbuf, smb_size);
3796 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3797 SCVAL(buf,smb_com,SMBwritebraw);
3798 SSVALS(buf,smb_vwv0,0xFFFF);
3800 if (!srv_send_smb(smbd_server_fd(),
3802 false, 0, /* no signing */
3803 IS_CONN_ENCRYPTED(conn),
3805 exit_server_cleanly("reply_writebraw: srv_send_smb "
3809 /* Now read the raw data into the buffer and write it */
3810 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3812 if (!NT_STATUS_IS_OK(status)) {
3813 exit_server_cleanly("secondary writebraw failed");
3816 /* Set up outbuf to return the correct size */
3817 reply_outbuf(req, 1, 0);
3819 if (numtowrite != 0) {
3821 if (numtowrite > 0xFFFF) {
3822 DEBUG(0,("reply_writebraw: Oversize secondary write "
3823 "raw requested (%u). Terminating\n",
3824 (unsigned int)numtowrite ));
3825 exit_server_cleanly("secondary writebraw failed");
3828 if (tcount > nwritten+numtowrite) {
3829 DEBUG(3,("reply_writebraw: Client overestimated the "
3831 (int)tcount,(int)nwritten,(int)numtowrite));
3834 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3836 if (!NT_STATUS_IS_OK(status)) {
3837 DEBUG(0,("reply_writebraw: Oversize secondary write "
3838 "raw read failed (%s). Terminating\n",
3839 nt_errstr(status)));
3840 exit_server_cleanly("secondary writebraw failed");
3843 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3844 if (nwritten == -1) {
3846 reply_unixerror(req, ERRHRD, ERRdiskfull);
3847 error_to_writebrawerr(req);
3851 if (nwritten < (ssize_t)numtowrite) {
3852 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3853 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3857 total_written += nwritten;
3862 SSVAL(req->outbuf,smb_vwv0,total_written);
3864 status = sync_file(conn, fsp, write_through);
3865 if (!NT_STATUS_IS_OK(status)) {
3866 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3867 fsp->fsp_name, nt_errstr(status) ));
3868 reply_nterror(req, status);
3869 error_to_writebrawerr(req);
3873 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3875 fsp->fnum, (double)startpos, (int)numtowrite,
3876 (int)total_written));
3878 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3880 /* We won't return a status if write through is not selected - this
3881 * follows what WfWg does */
3882 END_PROFILE(SMBwritebraw);
3884 if (!write_through && total_written==tcount) {
3886 #if RABBIT_PELLET_FIX
3888 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3889 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3892 if (!send_keepalive(smbd_server_fd())) {
3893 exit_server_cleanly("reply_writebraw: send of "
3894 "keepalive failed");
3897 TALLOC_FREE(req->outbuf);
3902 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3904 END_PROFILE(SMBwritebraw);
3909 #define DBGC_CLASS DBGC_LOCKING
3911 /****************************************************************************
3912 Reply to a writeunlock (core+).
3913 ****************************************************************************/
3915 void reply_writeunlock(struct smb_request *req)
3917 connection_struct *conn = req->conn;
3918 ssize_t nwritten = -1;
3922 NTSTATUS status = NT_STATUS_OK;
3924 struct lock_struct lock;
3926 START_PROFILE(SMBwriteunlock);
3929 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3930 END_PROFILE(SMBwriteunlock);
3934 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3936 if (!check_fsp(conn, req, fsp)) {
3937 END_PROFILE(SMBwriteunlock);
3941 if (!CHECK_WRITE(fsp)) {
3942 reply_doserror(req, ERRDOS,ERRbadaccess);
3943 END_PROFILE(SMBwriteunlock);
3947 numtowrite = SVAL(req->vwv+1, 0);
3948 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3949 data = (const char *)req->buf + 3;
3952 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3953 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3956 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3957 reply_doserror(req, ERRDOS, ERRlock);
3958 END_PROFILE(SMBwriteunlock);
3963 /* The special X/Open SMB protocol handling of
3964 zero length writes is *NOT* done for
3966 if(numtowrite == 0) {
3969 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3972 status = sync_file(conn, fsp, False /* write through */);
3973 if (!NT_STATUS_IS_OK(status)) {
3974 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3975 fsp->fsp_name, nt_errstr(status) ));
3976 reply_nterror(req, status);
3980 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3981 reply_unixerror(req, ERRHRD, ERRdiskfull);
3986 status = do_unlock(smbd_messaging_context(),
3989 (uint64_t)numtowrite,
3993 if (NT_STATUS_V(status)) {
3994 reply_nterror(req, status);
3999 reply_outbuf(req, 1, 0);
4001 SSVAL(req->outbuf,smb_vwv0,nwritten);
4003 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4004 fsp->fnum, (int)numtowrite, (int)nwritten));
4008 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4011 END_PROFILE(SMBwriteunlock);
4016 #define DBGC_CLASS DBGC_ALL
4018 /****************************************************************************
4020 ****************************************************************************/
4022 void reply_write(struct smb_request *req)
4024 connection_struct *conn = req->conn;
4026 ssize_t nwritten = -1;
4030 struct lock_struct lock;
4033 START_PROFILE(SMBwrite);
4036 END_PROFILE(SMBwrite);
4037 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4041 /* If it's an IPC, pass off the pipe handler. */
4043 reply_pipe_write(req);
4044 END_PROFILE(SMBwrite);
4048 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4050 if (!check_fsp(conn, req, fsp)) {
4051 END_PROFILE(SMBwrite);
4055 if (!CHECK_WRITE(fsp)) {
4056 reply_doserror(req, ERRDOS, ERRbadaccess);
4057 END_PROFILE(SMBwrite);
4061 numtowrite = SVAL(req->vwv+1, 0);
4062 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4063 data = (const char *)req->buf + 3;
4065 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4066 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4069 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4070 reply_doserror(req, ERRDOS, ERRlock);
4071 END_PROFILE(SMBwrite);
4076 * X/Open SMB protocol says that if smb_vwv1 is
4077 * zero then the file size should be extended or
4078 * truncated to the size given in smb_vwv[2-3].
4081 if(numtowrite == 0) {
4083 * This is actually an allocate call, and set EOF. JRA.
4085 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4087 reply_nterror(req, NT_STATUS_DISK_FULL);
4090 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4092 reply_nterror(req, NT_STATUS_DISK_FULL);
4095 trigger_write_time_update_immediate(fsp);
4097 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4100 status = sync_file(conn, fsp, False);
4101 if (!NT_STATUS_IS_OK(status)) {
4102 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4103 fsp->fsp_name, nt_errstr(status) ));
4104 reply_nterror(req, status);
4108 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4109 reply_unixerror(req, ERRHRD, ERRdiskfull);
4113 reply_outbuf(req, 1, 0);
4115 SSVAL(req->outbuf,smb_vwv0,nwritten);
4117 if (nwritten < (ssize_t)numtowrite) {
4118 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4119 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4122 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4125 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4127 END_PROFILE(SMBwrite);
4131 /****************************************************************************
4132 Ensure a buffer is a valid writeX for recvfile purposes.
4133 ****************************************************************************/
4135 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4136 (2*14) + /* word count (including bcc) */ \
4139 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4142 connection_struct *conn = NULL;
4143 unsigned int doff = 0;
4144 size_t len = smb_len_large(inbuf);
4145 struct smbd_server_connection *sconn = smbd_server_conn;
4147 if (is_encrypted_packet(inbuf)) {
4148 /* Can't do this on encrypted
4153 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4157 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4158 CVAL(inbuf,smb_wct) != 14) {
4159 DEBUG(10,("is_valid_writeX_buffer: chained or "
4160 "invalid word length.\n"));
4164 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4166 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4170 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4173 if (IS_PRINT(conn)) {
4174 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4177 doff = SVAL(inbuf,smb_vwv11);
4179 numtowrite = SVAL(inbuf,smb_vwv10);
4181 if (len > doff && len - doff > 0xFFFF) {
4182 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4185 if (numtowrite == 0) {
4186 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4190 /* Ensure the sizes match up. */
4191 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4192 /* no pad byte...old smbclient :-( */
4193 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4195 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4199 if (len - doff != numtowrite) {
4200 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4201 "len = %u, doff = %u, numtowrite = %u\n",
4204 (unsigned int)numtowrite ));
4208 DEBUG(10,("is_valid_writeX_buffer: true "
4209 "len = %u, doff = %u, numtowrite = %u\n",
4212 (unsigned int)numtowrite ));
4217 /****************************************************************************
4218 Reply to a write and X.
4219 ****************************************************************************/
4221 void reply_write_and_X(struct smb_request *req)
4223 connection_struct *conn = req->conn;
4225 struct lock_struct lock;
4230 unsigned int smb_doff;
4231 unsigned int smblen;
4235 START_PROFILE(SMBwriteX);
4237 if ((req->wct != 12) && (req->wct != 14)) {
4238 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4239 END_PROFILE(SMBwriteX);
4243 numtowrite = SVAL(req->vwv+10, 0);
4244 smb_doff = SVAL(req->vwv+11, 0);
4245 smblen = smb_len(req->inbuf);
4247 if (req->unread_bytes > 0xFFFF ||
4248 (smblen > smb_doff &&
4249 smblen - smb_doff > 0xFFFF)) {
4250 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4253 if (req->unread_bytes) {
4254 /* Can't do a recvfile write on IPC$ */
4256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4257 END_PROFILE(SMBwriteX);
4260 if (numtowrite != req->unread_bytes) {
4261 reply_doserror(req, ERRDOS, ERRbadmem);
4262 END_PROFILE(SMBwriteX);
4266 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4267 smb_doff + numtowrite > smblen) {
4268 reply_doserror(req, ERRDOS, ERRbadmem);
4269 END_PROFILE(SMBwriteX);
4274 /* If it's an IPC, pass off the pipe handler. */
4276 if (req->unread_bytes) {
4277 reply_doserror(req, ERRDOS, ERRbadmem);
4278 END_PROFILE(SMBwriteX);
4281 reply_pipe_write_and_X(req);
4282 END_PROFILE(SMBwriteX);
4286 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4287 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4288 write_through = BITSETW(req->vwv+7,0);
4290 if (!check_fsp(conn, req, fsp)) {
4291 END_PROFILE(SMBwriteX);
4295 if (!CHECK_WRITE(fsp)) {
4296 reply_doserror(req, ERRDOS, ERRbadaccess);
4297 END_PROFILE(SMBwriteX);
4301 data = smb_base(req->inbuf) + smb_doff;
4303 if(req->wct == 14) {
4304 #ifdef LARGE_SMB_OFF_T
4306 * This is a large offset (64 bit) write.
4308 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4310 #else /* !LARGE_SMB_OFF_T */
4313 * Ensure we haven't been sent a >32 bit offset.
4316 if(IVAL(req->vwv+12, 0) != 0) {
4317 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4318 "used and we don't support 64 bit offsets.\n",
4319 (unsigned int)IVAL(req->vwv+12, 0) ));
4320 reply_doserror(req, ERRDOS, ERRbadaccess);
4321 END_PROFILE(SMBwriteX);
4325 #endif /* LARGE_SMB_OFF_T */
4328 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4329 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4332 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4333 reply_doserror(req, ERRDOS, ERRlock);
4334 END_PROFILE(SMBwriteX);
4338 /* X/Open SMB protocol says that, unlike SMBwrite
4339 if the length is zero then NO truncation is
4340 done, just a write of zero. To truncate a file,
4343 if(numtowrite == 0) {
4347 if ((req->unread_bytes == 0) &&
4348 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4353 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4356 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4357 reply_unixerror(req, ERRHRD, ERRdiskfull);
4361 reply_outbuf(req, 6, 0);
4362 SSVAL(req->outbuf,smb_vwv2,nwritten);
4363 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4365 if (nwritten < (ssize_t)numtowrite) {
4366 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4367 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4370 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4371 fsp->fnum, (int)numtowrite, (int)nwritten));
4373 status = sync_file(conn, fsp, write_through);
4374 if (!NT_STATUS_IS_OK(status)) {
4375 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4376 fsp->fsp_name, nt_errstr(status) ));
4377 reply_nterror(req, status);
4381 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4383 END_PROFILE(SMBwriteX);
4388 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4390 END_PROFILE(SMBwriteX);
4394 /****************************************************************************
4396 ****************************************************************************/
4398 void reply_lseek(struct smb_request *req)
4400 connection_struct *conn = req->conn;
4406 START_PROFILE(SMBlseek);
4409 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4410 END_PROFILE(SMBlseek);
4414 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4416 if (!check_fsp(conn, req, fsp)) {
4420 flush_write_cache(fsp, SEEK_FLUSH);
4422 mode = SVAL(req->vwv+1, 0) & 3;
4423 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4424 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4433 res = fsp->fh->pos + startpos;
4444 if (umode == SEEK_END) {
4445 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4446 if(errno == EINVAL) {
4447 SMB_OFF_T current_pos = startpos;
4448 SMB_STRUCT_STAT sbuf;
4450 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4451 reply_unixerror(req, ERRDOS,
4453 END_PROFILE(SMBlseek);
4457 current_pos += sbuf.st_ex_size;
4459 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4464 reply_unixerror(req, ERRDOS, ERRnoaccess);
4465 END_PROFILE(SMBlseek);
4472 reply_outbuf(req, 2, 0);
4473 SIVAL(req->outbuf,smb_vwv0,res);
4475 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4476 fsp->fnum, (double)startpos, (double)res, mode));
4478 END_PROFILE(SMBlseek);
4482 /****************************************************************************
4484 ****************************************************************************/
4486 void reply_flush(struct smb_request *req)
4488 connection_struct *conn = req->conn;
4492 START_PROFILE(SMBflush);
4495 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4499 fnum = SVAL(req->vwv+0, 0);
4500 fsp = file_fsp(req, fnum);
4502 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4507 file_sync_all(conn);
4509 NTSTATUS status = sync_file(conn, fsp, True);
4510 if (!NT_STATUS_IS_OK(status)) {
4511 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4512 fsp->fsp_name, nt_errstr(status) ));
4513 reply_nterror(req, status);
4514 END_PROFILE(SMBflush);
4519 reply_outbuf(req, 0, 0);
4521 DEBUG(3,("flush\n"));
4522 END_PROFILE(SMBflush);
4526 /****************************************************************************
4528 conn POINTER CAN BE NULL HERE !
4529 ****************************************************************************/
4531 void reply_exit(struct smb_request *req)
4533 START_PROFILE(SMBexit);
4535 file_close_pid(req->smbpid, req->vuid);
4537 reply_outbuf(req, 0, 0);
4539 DEBUG(3,("exit\n"));
4541 END_PROFILE(SMBexit);
4545 /****************************************************************************
4546 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4547 ****************************************************************************/
4549 void reply_close(struct smb_request *req)
4551 connection_struct *conn = req->conn;
4552 NTSTATUS status = NT_STATUS_OK;
4553 files_struct *fsp = NULL;
4554 START_PROFILE(SMBclose);
4557 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4558 END_PROFILE(SMBclose);
4562 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4565 * We can only use check_fsp if we know it's not a directory.
4568 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4569 reply_doserror(req, ERRDOS, ERRbadfid);
4570 END_PROFILE(SMBclose);
4574 if(fsp->is_directory) {
4576 * Special case - close NT SMB directory handle.
4578 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4579 status = close_file(req, fsp, NORMAL_CLOSE);
4583 * Close ordinary file.
4586 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4587 fsp->fh->fd, fsp->fnum,
4588 conn->num_files_open));
4591 * Take care of any time sent in the close.
4594 t = srv_make_unix_date3(req->vwv+1);
4595 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4598 * close_file() returns the unix errno if an error
4599 * was detected on close - normally this is due to
4600 * a disk full error. If not then it was probably an I/O error.
4603 status = close_file(req, fsp, NORMAL_CLOSE);
4606 if (!NT_STATUS_IS_OK(status)) {
4607 reply_nterror(req, status);
4608 END_PROFILE(SMBclose);
4612 reply_outbuf(req, 0, 0);
4613 END_PROFILE(SMBclose);
4617 /****************************************************************************
4618 Reply to a writeclose (Core+ protocol).
4619 ****************************************************************************/
4621 void reply_writeclose(struct smb_request *req)
4623 connection_struct *conn = req->conn;
4625 ssize_t nwritten = -1;
4626 NTSTATUS close_status = NT_STATUS_OK;
4629 struct timespec mtime;
4631 struct lock_struct lock;
4633 START_PROFILE(SMBwriteclose);
4636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4637 END_PROFILE(SMBwriteclose);
4641 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4643 if (!check_fsp(conn, req, fsp)) {
4644 END_PROFILE(SMBwriteclose);
4647 if (!CHECK_WRITE(fsp)) {
4648 reply_doserror(req, ERRDOS,ERRbadaccess);
4649 END_PROFILE(SMBwriteclose);
4653 numtowrite = SVAL(req->vwv+1, 0);
4654 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4655 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4656 data = (const char *)req->buf + 1;
4659 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4660 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4663 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4664 reply_doserror(req, ERRDOS,ERRlock);
4665 END_PROFILE(SMBwriteclose);
4670 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4672 set_close_write_time(fsp, mtime);
4675 * More insanity. W2K only closes the file if writelen > 0.
4680 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4682 close_status = close_file(req, fsp, NORMAL_CLOSE);
4685 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4686 fsp->fnum, (int)numtowrite, (int)nwritten,
4687 conn->num_files_open));
4689 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4690 reply_doserror(req, ERRHRD, ERRdiskfull);
4694 if(!NT_STATUS_IS_OK(close_status)) {
4695 reply_nterror(req, close_status);
4699 reply_outbuf(req, 1, 0);
4701 SSVAL(req->outbuf,smb_vwv0,nwritten);
4705 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4708 END_PROFILE(SMBwriteclose);
4713 #define DBGC_CLASS DBGC_LOCKING
4715 /****************************************************************************
4717 ****************************************************************************/
4719 void reply_lock(struct smb_request *req)
4721 connection_struct *conn = req->conn;
4722 uint64_t count,offset;
4725 struct byte_range_lock *br_lck = NULL;
4727 START_PROFILE(SMBlock);
4730 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4731 END_PROFILE(SMBlock);
4735 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4737 if (!check_fsp(conn, req, fsp)) {
4738 END_PROFILE(SMBlock);
4742 count = (uint64_t)IVAL(req->vwv+1, 0);
4743 offset = (uint64_t)IVAL(req->vwv+3, 0);
4745 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4746 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4748 br_lck = do_lock(smbd_messaging_context(),
4755 False, /* Non-blocking lock. */
4760 TALLOC_FREE(br_lck);
4762 if (NT_STATUS_V(status)) {
4763 reply_nterror(req, status);
4764 END_PROFILE(SMBlock);
4768 reply_outbuf(req, 0, 0);
4770 END_PROFILE(SMBlock);
4774 /****************************************************************************
4776 ****************************************************************************/
4778 void reply_unlock(struct smb_request *req)
4780 connection_struct *conn = req->conn;
4781 uint64_t count,offset;
4785 START_PROFILE(SMBunlock);
4788 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4789 END_PROFILE(SMBunlock);
4793 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4795 if (!check_fsp(conn, req, fsp)) {
4796 END_PROFILE(SMBunlock);
4800 count = (uint64_t)IVAL(req->vwv+1, 0);
4801 offset = (uint64_t)IVAL(req->vwv+3, 0);
4803 status = do_unlock(smbd_messaging_context(),
4810 if (NT_STATUS_V(status)) {
4811 reply_nterror(req, status);
4812 END_PROFILE(SMBunlock);
4816 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4817 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4819 reply_outbuf(req, 0, 0);
4821 END_PROFILE(SMBunlock);
4826 #define DBGC_CLASS DBGC_ALL
4828 /****************************************************************************
4830 conn POINTER CAN BE NULL HERE !
4831 ****************************************************************************/
4833 void reply_tdis(struct smb_request *req)
4835 struct smbd_server_connection *sconn = smbd_server_conn;
4836 connection_struct *conn = req->conn;
4837 START_PROFILE(SMBtdis);
4840 DEBUG(4,("Invalid connection in tdis\n"));
4841 reply_doserror(req, ERRSRV, ERRinvnid);
4842 END_PROFILE(SMBtdis);
4848 close_cnum(sconn, conn,req->vuid);
4851 reply_outbuf(req, 0, 0);
4852 END_PROFILE(SMBtdis);
4856 /****************************************************************************
4858 conn POINTER CAN BE NULL HERE !
4859 ****************************************************************************/
4861 void reply_echo(struct smb_request *req)
4863 connection_struct *conn = req->conn;
4864 struct smb_perfcount_data local_pcd;
4865 struct smb_perfcount_data *cur_pcd;
4869 START_PROFILE(SMBecho);
4871 smb_init_perfcount_data(&local_pcd);
4874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4875 END_PROFILE(SMBecho);
4879 smb_reverb = SVAL(req->vwv+0, 0);
4881 reply_outbuf(req, 1, req->buflen);
4883 /* copy any incoming data back out */
4884 if (req->buflen > 0) {
4885 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4888 if (smb_reverb > 100) {
4889 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4893 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4895 /* this makes sure we catch the request pcd */
4896 if (seq_num == smb_reverb) {
4897 cur_pcd = &req->pcd;
4899 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4900 cur_pcd = &local_pcd;
4903 SSVAL(req->outbuf,smb_vwv0,seq_num);
4905 show_msg((char *)req->outbuf);
4906 if (!srv_send_smb(smbd_server_fd(),
4907 (char *)req->outbuf,
4908 true, req->seqnum+1,
4909 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4911 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4914 DEBUG(3,("echo %d times\n", smb_reverb));
4916 TALLOC_FREE(req->outbuf);
4918 END_PROFILE(SMBecho);
4922 /****************************************************************************
4923 Reply to a printopen.
4924 ****************************************************************************/
4926 void reply_printopen(struct smb_request *req)
4928 connection_struct *conn = req->conn;
4930 SMB_STRUCT_STAT sbuf;
4933 START_PROFILE(SMBsplopen);
4936 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4937 END_PROFILE(SMBsplopen);
4941 if (!CAN_PRINT(conn)) {
4942 reply_doserror(req, ERRDOS, ERRnoaccess);
4943 END_PROFILE(SMBsplopen);
4947 status = file_new(req, conn, &fsp);
4948 if(!NT_STATUS_IS_OK(status)) {
4949 reply_nterror(req, status);
4950 END_PROFILE(SMBsplopen);
4954 /* Open for exclusive use, write only. */
4955 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4957 if (!NT_STATUS_IS_OK(status)) {
4958 file_free(req, fsp);
4959 reply_nterror(req, status);
4960 END_PROFILE(SMBsplopen);
4964 reply_outbuf(req, 1, 0);
4965 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4967 DEBUG(3,("openprint fd=%d fnum=%d\n",
4968 fsp->fh->fd, fsp->fnum));
4970 END_PROFILE(SMBsplopen);
4974 /****************************************************************************
4975 Reply to a printclose.
4976 ****************************************************************************/
4978 void reply_printclose(struct smb_request *req)
4980 connection_struct *conn = req->conn;
4984 START_PROFILE(SMBsplclose);
4987 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4988 END_PROFILE(SMBsplclose);
4992 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4994 if (!check_fsp(conn, req, fsp)) {
4995 END_PROFILE(SMBsplclose);
4999 if (!CAN_PRINT(conn)) {
5000 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
5001 END_PROFILE(SMBsplclose);
5005 DEBUG(3,("printclose fd=%d fnum=%d\n",
5006 fsp->fh->fd,fsp->fnum));
5008 status = close_file(req, fsp, NORMAL_CLOSE);
5010 if(!NT_STATUS_IS_OK(status)) {
5011 reply_nterror(req, status);
5012 END_PROFILE(SMBsplclose);
5016 reply_outbuf(req, 0, 0);
5018 END_PROFILE(SMBsplclose);
5022 /****************************************************************************
5023 Reply to a printqueue.
5024 ****************************************************************************/
5026 void reply_printqueue(struct smb_request *req)
5028 connection_struct *conn = req->conn;
5032 START_PROFILE(SMBsplretq);
5035 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5036 END_PROFILE(SMBsplretq);
5040 max_count = SVAL(req->vwv+0, 0);
5041 start_index = SVAL(req->vwv+1, 0);
5043 /* we used to allow the client to get the cnum wrong, but that
5044 is really quite gross and only worked when there was only
5045 one printer - I think we should now only accept it if they
5046 get it right (tridge) */
5047 if (!CAN_PRINT(conn)) {
5048 reply_doserror(req, ERRDOS, ERRnoaccess);
5049 END_PROFILE(SMBsplretq);
5053 reply_outbuf(req, 2, 3);
5054 SSVAL(req->outbuf,smb_vwv0,0);
5055 SSVAL(req->outbuf,smb_vwv1,0);
5056 SCVAL(smb_buf(req->outbuf),0,1);
5057 SSVAL(smb_buf(req->outbuf),1,0);
5059 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5060 start_index, max_count));
5063 print_queue_struct *queue = NULL;
5064 print_status_struct status;
5065 int count = print_queue_status(SNUM(conn), &queue, &status);
5066 int num_to_get = ABS(max_count);
5067 int first = (max_count>0?start_index:start_index+max_count+1);
5073 num_to_get = MIN(num_to_get,count-first);
5076 for (i=first;i<first+num_to_get;i++) {
5080 srv_put_dos_date2(p,0,queue[i].time);
5081 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5082 SSVAL(p,5, queue[i].job);
5083 SIVAL(p,7,queue[i].size);
5085 srvstr_push(blob, req->flags2, p+12,
5086 queue[i].fs_user, 16, STR_ASCII);
5088 if (message_push_blob(
5091 blob, sizeof(blob))) == -1) {
5092 reply_nterror(req, NT_STATUS_NO_MEMORY);
5093 END_PROFILE(SMBsplretq);
5099 SSVAL(req->outbuf,smb_vwv0,count);
5100 SSVAL(req->outbuf,smb_vwv1,
5101 (max_count>0?first+count:first-1));
5102 SCVAL(smb_buf(req->outbuf),0,1);
5103 SSVAL(smb_buf(req->outbuf),1,28*count);
5108 DEBUG(3,("%d entries returned in queue\n",count));
5111 END_PROFILE(SMBsplretq);
5115 /****************************************************************************
5116 Reply to a printwrite.
5117 ****************************************************************************/
5119 void reply_printwrite(struct smb_request *req)
5121 connection_struct *conn = req->conn;
5126 START_PROFILE(SMBsplwr);
5129 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5130 END_PROFILE(SMBsplwr);
5134 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5136 if (!check_fsp(conn, req, fsp)) {
5137 END_PROFILE(SMBsplwr);
5141 if (!CAN_PRINT(conn)) {
5142 reply_doserror(req, ERRDOS, ERRnoaccess);
5143 END_PROFILE(SMBsplwr);
5147 if (!CHECK_WRITE(fsp)) {
5148 reply_doserror(req, ERRDOS, ERRbadaccess);
5149 END_PROFILE(SMBsplwr);
5153 numtowrite = SVAL(req->buf, 1);
5155 if (req->buflen < numtowrite + 3) {
5156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5157 END_PROFILE(SMBsplwr);
5161 data = (const char *)req->buf + 3;
5163 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5164 reply_unixerror(req, ERRHRD, ERRdiskfull);
5165 END_PROFILE(SMBsplwr);
5169 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5171 END_PROFILE(SMBsplwr);
5175 /****************************************************************************
5177 ****************************************************************************/
5179 void reply_mkdir(struct smb_request *req)
5181 connection_struct *conn = req->conn;
5182 struct smb_filename *smb_dname = NULL;
5183 char *directory = NULL;
5185 TALLOC_CTX *ctx = talloc_tos();
5187 START_PROFILE(SMBmkdir);
5189 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5190 STR_TERMINATE, &status);
5191 if (!NT_STATUS_IS_OK(status)) {
5192 reply_nterror(req, status);
5196 status = filename_convert(ctx, conn,
5197 req->flags2 & FLAGS2_DFS_PATHNAMES,
5201 if (!NT_STATUS_IS_OK(status)) {
5202 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5203 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5204 ERRSRV, ERRbadpath);
5207 reply_nterror(req, status);
5211 status = create_directory(conn, req, smb_dname);
5213 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5215 if (!NT_STATUS_IS_OK(status)) {
5217 if (!use_nt_status()
5218 && NT_STATUS_EQUAL(status,
5219 NT_STATUS_OBJECT_NAME_COLLISION)) {
5221 * Yes, in the DOS error code case we get a
5222 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5223 * samba4 torture test.
5225 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5228 reply_nterror(req, status);
5232 reply_outbuf(req, 0, 0);
5234 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5236 TALLOC_FREE(smb_dname);
5237 END_PROFILE(SMBmkdir);
5241 /****************************************************************************
5242 Static function used by reply_rmdir to delete an entire directory
5243 tree recursively. Return True on ok, False on fail.
5244 ****************************************************************************/
5246 static bool recursive_rmdir(TALLOC_CTX *ctx,
5247 connection_struct *conn,
5250 const char *dname = NULL;
5254 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5260 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5261 char *fullname = NULL;
5262 struct smb_filename *smb_fname = NULL;
5265 if (ISDOT(dname) || ISDOTDOT(dname)) {
5269 if (!is_visible_file(conn, directory, dname, &st, False)) {
5273 /* Construct the full name. */
5274 fullname = talloc_asprintf(ctx,
5283 status = create_synthetic_smb_fname(talloc_tos(), fullname,
5284 NULL, NULL, &smb_fname);
5285 if (!NT_STATUS_IS_OK(status)) {
5289 if(SMB_VFS_LSTAT(conn, smb_fname) != 0) {
5293 if(smb_fname->st.st_ex_mode & S_IFDIR) {
5294 if(!recursive_rmdir(ctx, conn, fullname)) {
5297 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5300 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5303 TALLOC_FREE(smb_fname);
5304 TALLOC_FREE(fullname);
5307 TALLOC_FREE(smb_fname);
5308 TALLOC_FREE(fullname);
5312 TALLOC_FREE(dir_hnd);
5316 /****************************************************************************
5317 The internals of the rmdir code - called elsewhere.
5318 ****************************************************************************/
5320 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5321 connection_struct *conn,
5322 const char *directory)
5327 /* Might be a symlink. */
5328 if(vfs_lstat_smb_fname(conn, directory, &st) != 0) {
5329 return map_nt_error_from_unix(errno);
5332 if (S_ISLNK(st.st_ex_mode)) {
5333 /* Is what it points to a directory ? */
5334 if(vfs_stat_smb_fname(conn, directory, &st) != 0) {
5335 return map_nt_error_from_unix(errno);
5337 if (!(S_ISDIR(st.st_ex_mode))) {
5338 return NT_STATUS_NOT_A_DIRECTORY;
5340 ret = SMB_VFS_UNLINK(conn,directory);
5342 ret = SMB_VFS_RMDIR(conn,directory);
5345 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5346 FILE_NOTIFY_CHANGE_DIR_NAME,
5348 return NT_STATUS_OK;
5351 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5353 * Check to see if the only thing in this directory are
5354 * vetoed files/directories. If so then delete them and
5355 * retry. If we fail to delete any of them (and we *don't*
5356 * do a recursive delete) then fail the rmdir.
5360 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5361 directory, NULL, 0);
5363 if(dir_hnd == NULL) {
5368 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5369 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5371 if (!is_visible_file(conn, directory, dname, &st, False))
5373 if(!IS_VETO_PATH(conn, dname)) {
5374 TALLOC_FREE(dir_hnd);
5380 /* We only have veto files/directories.
5381 * Are we allowed to delete them ? */
5383 if(!lp_recursive_veto_delete(SNUM(conn))) {
5384 TALLOC_FREE(dir_hnd);
5389 /* Do a recursive delete. */
5390 RewindDir(dir_hnd,&dirpos);
5391 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5392 char *fullname = NULL;
5394 if (ISDOT(dname) || ISDOTDOT(dname)) {
5397 if (!is_visible_file(conn, directory, dname, &st, False)) {
5401 fullname = talloc_asprintf(ctx,
5411 if(vfs_lstat_smb_fname(conn,fullname, &st) != 0) {
5414 if(st.st_ex_mode & S_IFDIR) {
5415 if(!recursive_rmdir(ctx, conn, fullname)) {
5418 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5421 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5424 TALLOC_FREE(fullname);
5426 TALLOC_FREE(dir_hnd);
5427 /* Retry the rmdir */
5428 ret = SMB_VFS_RMDIR(conn,directory);
5434 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5435 "%s\n", directory,strerror(errno)));
5436 return map_nt_error_from_unix(errno);
5439 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5440 FILE_NOTIFY_CHANGE_DIR_NAME,
5443 return NT_STATUS_OK;
5446 /****************************************************************************
5448 ****************************************************************************/
5450 void reply_rmdir(struct smb_request *req)
5452 connection_struct *conn = req->conn;
5453 struct smb_filename *smb_dname = NULL;
5454 char *directory = NULL;
5456 TALLOC_CTX *ctx = talloc_tos();
5458 START_PROFILE(SMBrmdir);
5460 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5461 STR_TERMINATE, &status);
5462 if (!NT_STATUS_IS_OK(status)) {
5463 reply_nterror(req, status);
5467 status = filename_convert(ctx, conn,
5468 req->flags2 & FLAGS2_DFS_PATHNAMES,
5472 if (!NT_STATUS_IS_OK(status)) {
5473 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5474 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5475 ERRSRV, ERRbadpath);
5478 reply_nterror(req, status);
5482 dptr_closepath(directory, req->smbpid);
5483 status = rmdir_internals(ctx, conn, directory);
5484 if (!NT_STATUS_IS_OK(status)) {
5485 reply_nterror(req, status);
5489 reply_outbuf(req, 0, 0);
5491 DEBUG( 3, ( "rmdir %s\n", directory ) );
5493 TALLOC_FREE(smb_dname);
5494 END_PROFILE(SMBrmdir);
5498 /*******************************************************************
5499 Resolve wildcards in a filename rename.
5500 ********************************************************************/
5502 static bool resolve_wildcards(TALLOC_CTX *ctx,
5507 char *name2_copy = NULL;
5512 char *p,*p2, *pname1, *pname2;
5514 name2_copy = talloc_strdup(ctx, name2);
5519 pname1 = strrchr_m(name1,'/');
5520 pname2 = strrchr_m(name2_copy,'/');
5522 if (!pname1 || !pname2) {
5526 /* Truncate the copy of name2 at the last '/' */
5529 /* Now go past the '/' */
5533 root1 = talloc_strdup(ctx, pname1);
5534 root2 = talloc_strdup(ctx, pname2);
5536 if (!root1 || !root2) {
5540 p = strrchr_m(root1,'.');
5543 ext1 = talloc_strdup(ctx, p+1);
5545 ext1 = talloc_strdup(ctx, "");
5547 p = strrchr_m(root2,'.');
5550 ext2 = talloc_strdup(ctx, p+1);
5552 ext2 = talloc_strdup(ctx, "");
5555 if (!ext1 || !ext2) {
5563 /* Hmmm. Should this be mb-aware ? */
5566 } else if (*p2 == '*') {
5568 root2 = talloc_asprintf(ctx, "%s%s",
5587 /* Hmmm. Should this be mb-aware ? */
5590 } else if (*p2 == '*') {
5592 ext2 = talloc_asprintf(ctx, "%s%s",
5608 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5613 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5625 /****************************************************************************
5626 Ensure open files have their names updated. Updated to notify other smbd's
5628 ****************************************************************************/
5630 static void rename_open_files(connection_struct *conn,
5631 struct share_mode_lock *lck,
5632 const char *newname)
5635 bool did_rename = False;
5637 for(fsp = file_find_di_first(lck->id); fsp;
5638 fsp = file_find_di_next(fsp)) {
5639 /* fsp_name is a relative path under the fsp. To change this for other
5640 sharepaths we need to manipulate relative paths. */
5641 /* TODO - create the absolute path and manipulate the newname
5642 relative to the sharepath. */
5643 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5646 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5647 fsp->fnum, file_id_string_tos(&fsp->file_id),
5648 fsp->fsp_name, newname ));
5649 string_set(&fsp->fsp_name, newname);
5654 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5655 file_id_string_tos(&lck->id), newname ));
5658 /* Send messages to all smbd's (not ourself) that the name has changed. */
5659 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5663 /****************************************************************************
5664 We need to check if the source path is a parent directory of the destination
5665 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5666 refuse the rename with a sharing violation. Under UNIX the above call can
5667 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5668 probably need to check that the client is a Windows one before disallowing
5669 this as a UNIX client (one with UNIX extensions) can know the source is a
5670 symlink and make this decision intelligently. Found by an excellent bug
5671 report from <AndyLiebman@aol.com>.
5672 ****************************************************************************/
5674 static bool rename_path_prefix_equal(const char *src, const char *dest)
5676 const char *psrc = src;
5677 const char *pdst = dest;
5680 if (psrc[0] == '.' && psrc[1] == '/') {
5683 if (pdst[0] == '.' && pdst[1] == '/') {
5686 if ((slen = strlen(psrc)) > strlen(pdst)) {
5689 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5693 * Do the notify calls from a rename
5696 static void notify_rename(connection_struct *conn, bool is_dir,
5697 const char *oldpath, const char *newpath)
5699 char *olddir, *newdir;
5700 const char *oldname, *newname;
5703 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5704 : FILE_NOTIFY_CHANGE_FILE_NAME;
5706 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5707 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5708 TALLOC_FREE(olddir);
5712 if (strcmp(olddir, newdir) == 0) {
5713 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5714 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5717 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5718 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5720 TALLOC_FREE(olddir);
5721 TALLOC_FREE(newdir);
5723 /* this is a strange one. w2k3 gives an additional event for
5724 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5725 files, but not directories */
5727 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5728 FILE_NOTIFY_CHANGE_ATTRIBUTES
5729 |FILE_NOTIFY_CHANGE_CREATION,
5734 /****************************************************************************
5735 Rename an open file - given an fsp.
5736 ****************************************************************************/
5738 NTSTATUS rename_internals_fsp(connection_struct *conn,
5741 const char *newname_last_component,
5743 bool replace_if_exists)
5745 TALLOC_CTX *ctx = talloc_tos();
5746 SMB_STRUCT_STAT sbuf, sbuf1;
5747 NTSTATUS status = NT_STATUS_OK;
5748 struct share_mode_lock *lck = NULL;
5749 bool dst_exists, old_is_stream, new_is_stream;
5753 status = check_name(conn, newname);
5754 if (!NT_STATUS_IS_OK(status)) {
5758 /* Ensure newname contains a '/' */
5759 if(strrchr_m(newname,'/') == 0) {
5760 newname = talloc_asprintf(ctx,
5764 return NT_STATUS_NO_MEMORY;
5769 * Check for special case with case preserving and not
5770 * case sensitive. If the old last component differs from the original
5771 * last component only by case, then we should allow
5772 * the rename (user is trying to change the case of the
5776 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5777 strequal(newname, fsp->fsp_name)) {
5779 char *newname_modified_last_component = NULL;
5782 * Get the last component of the modified name.
5783 * Note that we guarantee that newname contains a '/'
5786 p = strrchr_m(newname,'/');
5787 newname_modified_last_component = talloc_strdup(ctx,
5789 if (!newname_modified_last_component) {
5790 return NT_STATUS_NO_MEMORY;
5793 if(strcsequal(newname_modified_last_component,
5794 newname_last_component) == False) {
5796 * Replace the modified last component with
5799 *p = '\0'; /* Truncate at the '/' */
5800 newname = talloc_asprintf(ctx,
5803 newname_last_component);
5808 * If the src and dest names are identical - including case,
5809 * don't do the rename, just return success.
5812 if (strcsequal(fsp->fsp_name, newname)) {
5813 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5815 return NT_STATUS_OK;
5818 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5819 new_is_stream = is_ntfs_stream_name(newname);
5821 /* Return the correct error code if both names aren't streams. */
5822 if (!old_is_stream && new_is_stream) {
5823 return NT_STATUS_OBJECT_NAME_INVALID;
5826 if (old_is_stream && !new_is_stream) {
5827 return NT_STATUS_INVALID_PARAMETER;
5830 dst_exists = vfs_stat_smb_fname(conn, newname, &sbuf1) == 0;
5832 if(!replace_if_exists && dst_exists) {
5833 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5834 fsp->fsp_name,newname));
5835 return NT_STATUS_OBJECT_NAME_COLLISION;
5839 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5840 files_struct *dst_fsp = file_find_di_first(fileid);
5841 /* The file can be open when renaming a stream */
5842 if (dst_fsp && !new_is_stream) {
5843 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5844 return NT_STATUS_ACCESS_DENIED;
5848 /* Ensure we have a valid stat struct for the source. */
5849 if (fsp->fh->fd != -1) {
5850 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5851 return map_nt_error_from_unix(errno);
5855 if (fsp->posix_open) {
5856 ret = vfs_lstat_smb_fname(conn,fsp->fsp_name,&sbuf);
5859 ret = vfs_stat_smb_fname(conn,fsp->fsp_name,&sbuf);
5862 return map_nt_error_from_unix(errno);
5866 status = can_rename(conn, fsp, attrs, &sbuf);
5868 if (!NT_STATUS_IS_OK(status)) {
5869 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5870 nt_errstr(status), fsp->fsp_name,newname));
5871 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5872 status = NT_STATUS_ACCESS_DENIED;
5876 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5877 return NT_STATUS_ACCESS_DENIED;
5880 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5884 * We have the file open ourselves, so not being able to get the
5885 * corresponding share mode lock is a fatal error.
5888 SMB_ASSERT(lck != NULL);
5890 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5891 uint32 create_options = fsp->fh->private_options;
5893 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5894 fsp->fsp_name,newname));
5896 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5898 rename_open_files(conn, lck, newname);
5901 * A rename acts as a new file create w.r.t. allowing an initial delete
5902 * on close, probably because in Windows there is a new handle to the
5903 * new file. If initial delete on close was requested but not
5904 * originally set, we need to set it here. This is probably not 100% correct,
5905 * but will work for the CIFSFS client which in non-posix mode
5906 * depends on these semantics. JRA.
5909 if (create_options & FILE_DELETE_ON_CLOSE) {
5910 status = can_set_delete_on_close(fsp, True, 0);
5912 if (NT_STATUS_IS_OK(status)) {
5913 /* Note that here we set the *inital* delete on close flag,
5914 * not the regular one. The magic gets handled in close. */
5915 fsp->initial_delete_on_close = True;
5919 return NT_STATUS_OK;
5924 if (errno == ENOTDIR || errno == EISDIR) {
5925 status = NT_STATUS_OBJECT_NAME_COLLISION;
5927 status = map_nt_error_from_unix(errno);
5930 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5931 nt_errstr(status), fsp->fsp_name,newname));
5936 /****************************************************************************
5937 The guts of the rename command, split out so it may be called by the NT SMB
5939 ****************************************************************************/
5941 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5942 connection_struct *conn,
5943 struct smb_request *req,
5944 const char *name_in,
5945 const char *newname_in,
5947 bool replace_if_exists,
5950 uint32_t access_mask)
5952 struct smb_filename *smb_fname_src = NULL;
5953 struct smb_filename *smb_fname_dst = NULL;
5954 char *fname_src_dir = NULL;
5955 char *fname_src_mask = NULL;
5957 NTSTATUS status = NT_STATUS_OK;
5958 struct smb_Dir *dir_hnd = NULL;
5961 int create_options = 0;
5962 bool posix_pathnames = lp_posix_pathnames();
5964 status = unix_convert(ctx, conn, name_in, &smb_fname_src,
5965 src_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
5966 if (!NT_STATUS_IS_OK(status)) {
5970 status = unix_convert(ctx, conn, newname_in, &smb_fname_dst,
5972 (dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0)));
5973 if (!NT_STATUS_IS_OK(status)) {
5978 * Split the old name into directory and last component
5979 * strings. Note that unix_convert may have stripped off a
5980 * leading ./ from both name and newname if the rename is
5981 * at the root of the share. We need to make sure either both
5982 * name and newname contain a / character or neither of them do
5983 * as this is checked in resolve_wildcards().
5986 /* Split up the directory from the filename/mask. */
5987 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
5988 &fname_src_dir, &fname_src_mask);
5989 if (!NT_STATUS_IS_OK(status)) {
5990 status = NT_STATUS_NO_MEMORY;
5995 * We should only check the mangled cache
5996 * here if unix_convert failed. This means
5997 * that the path in 'mask' doesn't exist
5998 * on the file system and so we need to look
5999 * for a possible mangle. This patch from
6000 * Tine Smukavec <valentin.smukavec@hermes.si>.
6003 if (!VALID_STAT(smb_fname_src->st) &&
6004 mangle_is_mangled(fname_src_mask, conn->params)) {
6005 char *new_mask = NULL;
6006 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6009 TALLOC_FREE(fname_src_mask);
6010 fname_src_mask = new_mask;
6014 if (!src_has_wild) {
6016 char *fname_dst = NULL;
6019 * Only one file needs to be renamied. Append the mask back
6020 * onto the directory.
6022 TALLOC_FREE(smb_fname_src->base_name);
6023 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6027 if (!smb_fname_src->base_name) {
6028 status = NT_STATUS_NO_MEMORY;
6032 /* Ensure dst fname contains a '/' also */
6033 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6035 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6036 smb_fname_dst->base_name);
6038 status = NT_STATUS_NO_MEMORY;
6041 TALLOC_FREE(smb_fname_dst->base_name);
6042 smb_fname_dst->base_name = tmp;
6045 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6046 "case_preserve = %d, short case preserve = %d, "
6047 "directory = %s, newname = %s, "
6048 "last_component_dest = %s\n",
6049 conn->case_sensitive, conn->case_preserve,
6050 conn->short_case_preserve,
6051 smb_fname_str_dbg(smb_fname_src),
6052 smb_fname_str_dbg(smb_fname_dst),
6053 smb_fname_dst->original_lcomp));
6055 /* The dest name still may have wildcards. */
6056 if (dest_has_wild) {
6057 char *fname_dst_mod = NULL;
6058 if (!resolve_wildcards(smb_fname_dst,
6059 smb_fname_src->base_name,
6060 smb_fname_dst->base_name,
6062 DEBUG(6, ("rename_internals: resolve_wildcards "
6064 smb_fname_src->base_name,
6065 smb_fname_dst->base_name));
6066 status = NT_STATUS_NO_MEMORY;
6069 TALLOC_FREE(smb_fname_dst->base_name);
6070 smb_fname_dst->base_name = fname_dst_mod;
6073 ZERO_STRUCT(smb_fname_src->st);
6074 if (posix_pathnames) {
6075 SMB_VFS_LSTAT(conn, smb_fname_src);
6077 SMB_VFS_STAT(conn, smb_fname_src);
6080 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6081 create_options |= FILE_DIRECTORY_FILE;
6084 status = SMB_VFS_CREATE_FILE(
6087 0, /* root_dir_fid */
6088 smb_fname_src, /* fname */
6089 access_mask, /* access_mask */
6090 (FILE_SHARE_READ | /* share_access */
6092 FILE_OPEN, /* create_disposition*/
6093 create_options, /* create_options */
6094 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6095 0, /* oplock_request */
6096 0, /* allocation_size */
6102 if (!NT_STATUS_IS_OK(status)) {
6103 DEBUG(3, ("Could not open rename source %s: %s\n",
6104 smb_fname_str_dbg(smb_fname_src),
6105 nt_errstr(status)));
6109 status = get_full_smb_filename(ctx, smb_fname_dst, &fname_dst);
6110 if (!NT_STATUS_IS_OK(status)) {
6114 status = rename_internals_fsp(conn, fsp, fname_dst,
6115 smb_fname_dst->original_lcomp,
6116 attrs, replace_if_exists);
6118 TALLOC_FREE(fname_dst);
6120 close_file(req, fsp, NORMAL_CLOSE);
6122 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6123 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6124 smb_fname_str_dbg(smb_fname_dst)));
6130 * Wildcards - process each file that matches.
6132 if (strequal(fname_src_mask, "????????.???")) {
6133 TALLOC_FREE(fname_src_mask);
6134 fname_src_mask = talloc_strdup(ctx, "*");
6135 if (!fname_src_mask) {
6136 status = NT_STATUS_NO_MEMORY;
6141 status = check_name(conn, fname_src_dir);
6142 if (!NT_STATUS_IS_OK(status)) {
6146 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6148 if (dir_hnd == NULL) {
6149 status = map_nt_error_from_unix(errno);
6153 status = NT_STATUS_NO_SUCH_FILE;
6155 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6156 * - gentest fix. JRA
6159 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
6160 files_struct *fsp = NULL;
6161 char *fname_dst = NULL;
6162 char *destname = NULL;
6163 bool sysdir_entry = False;
6165 /* Quick check for "." and ".." */
6166 if (ISDOT(dname) || ISDOTDOT(dname)) {
6168 sysdir_entry = True;
6174 if (!is_visible_file(conn, fname_src_dir, dname,
6175 &smb_fname_src->st, false)) {
6179 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6184 status = NT_STATUS_OBJECT_NAME_INVALID;
6188 TALLOC_FREE(smb_fname_src->base_name);
6189 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6193 if (!smb_fname_src->base_name) {
6194 status = NT_STATUS_NO_MEMORY;
6198 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6199 smb_fname_dst->base_name,
6201 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6202 smb_fname_src->base_name, destname));
6206 status = NT_STATUS_NO_MEMORY;
6210 TALLOC_FREE(smb_fname_dst->base_name);
6211 smb_fname_dst->base_name = destname;
6213 ZERO_STRUCT(smb_fname_src->st);
6214 if (posix_pathnames) {
6215 SMB_VFS_LSTAT(conn, smb_fname_src);
6217 SMB_VFS_STAT(conn, smb_fname_src);
6222 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6223 create_options |= FILE_DIRECTORY_FILE;
6226 status = SMB_VFS_CREATE_FILE(
6229 0, /* root_dir_fid */
6230 smb_fname_src, /* fname */
6231 access_mask, /* access_mask */
6232 (FILE_SHARE_READ | /* share_access */
6234 FILE_OPEN, /* create_disposition*/
6235 create_options, /* create_options */
6236 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6237 0, /* oplock_request */
6238 0, /* allocation_size */
6244 if (!NT_STATUS_IS_OK(status)) {
6245 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6246 "returned %s rename %s -> %s\n",
6248 smb_fname_str_dbg(smb_fname_src),
6249 smb_fname_str_dbg(smb_fname_dst)));
6253 status = get_full_smb_filename(ctx, smb_fname_dst, &fname_dst);
6254 if (!NT_STATUS_IS_OK(status)) {
6258 status = rename_internals_fsp(conn, fsp, fname_dst, dname,
6259 attrs, replace_if_exists);
6261 TALLOC_FREE(fname_dst);
6263 close_file(req, fsp, NORMAL_CLOSE);
6265 if (!NT_STATUS_IS_OK(status)) {
6266 DEBUG(3, ("rename_internals_fsp returned %s for "
6267 "rename %s -> %s\n", nt_errstr(status),
6268 smb_fname_str_dbg(smb_fname_src),
6269 smb_fname_str_dbg(smb_fname_dst)));
6275 DEBUG(3,("rename_internals: doing rename on %s -> "
6276 "%s\n", smb_fname_str_dbg(smb_fname_src),
6277 smb_fname_str_dbg(smb_fname_src)));
6280 TALLOC_FREE(dir_hnd);
6282 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6283 status = map_nt_error_from_unix(errno);
6287 TALLOC_FREE(smb_fname_src);
6288 TALLOC_FREE(smb_fname_dst);
6289 TALLOC_FREE(fname_src_dir);
6290 TALLOC_FREE(fname_src_mask);
6294 /****************************************************************************
6296 ****************************************************************************/
6298 void reply_mv(struct smb_request *req)
6300 connection_struct *conn = req->conn;
6302 char *newname = NULL;
6306 bool src_has_wcard = False;
6307 bool dest_has_wcard = False;
6308 TALLOC_CTX *ctx = talloc_tos();
6310 START_PROFILE(SMBmv);
6313 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6318 attrs = SVAL(req->vwv+0, 0);
6320 p = (const char *)req->buf + 1;
6321 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6322 &status, &src_has_wcard);
6323 if (!NT_STATUS_IS_OK(status)) {
6324 reply_nterror(req, status);
6329 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6330 &status, &dest_has_wcard);
6331 if (!NT_STATUS_IS_OK(status)) {
6332 reply_nterror(req, status);
6337 status = resolve_dfspath_wcard(ctx, conn,
6338 req->flags2 & FLAGS2_DFS_PATHNAMES,
6342 if (!NT_STATUS_IS_OK(status)) {
6343 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6344 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6345 ERRSRV, ERRbadpath);
6349 reply_nterror(req, status);
6354 status = resolve_dfspath_wcard(ctx, conn,
6355 req->flags2 & FLAGS2_DFS_PATHNAMES,
6359 if (!NT_STATUS_IS_OK(status)) {
6360 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6361 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6362 ERRSRV, ERRbadpath);
6366 reply_nterror(req, status);
6371 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6373 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6374 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6375 if (!NT_STATUS_IS_OK(status)) {
6376 if (open_was_deferred(req->mid)) {
6377 /* We have re-scheduled this call. */
6381 reply_nterror(req, status);
6386 reply_outbuf(req, 0, 0);
6392 /*******************************************************************
6393 Copy a file as part of a reply_copy.
6394 ******************************************************************/
6397 * TODO: check error codes on all callers
6400 NTSTATUS copy_file(TALLOC_CTX *ctx,
6401 connection_struct *conn,
6402 struct smb_filename *smb_fname_src,
6403 struct smb_filename *smb_fname_dst,
6406 bool target_is_directory)
6408 struct smb_filename *smb_fname_dst_tmp = NULL;
6409 char *fname_src = NULL;
6411 files_struct *fsp1,*fsp2;
6413 uint32 new_create_disposition;
6417 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6418 if (!NT_STATUS_IS_OK(status)) {
6423 * If the target is a directory, extract the last component from the
6424 * src filename and append it to the dst filename
6426 if (target_is_directory) {
6429 /* dest/target can't be a stream if it's a directory. */
6430 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6432 p = strrchr_m(smb_fname_src->base_name,'/');
6436 p = smb_fname_src->base_name;
6438 smb_fname_dst_tmp->base_name =
6439 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6441 if (!smb_fname_dst_tmp->base_name) {
6442 status = NT_STATUS_NO_MEMORY;
6447 status = vfs_file_exist(conn, smb_fname_src);
6448 if (!NT_STATUS_IS_OK(status)) {
6452 if (!target_is_directory && count) {
6453 new_create_disposition = FILE_OPEN;
6455 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6456 0, ofun, NULL, NULL,
6457 &new_create_disposition,
6459 status = NT_STATUS_INVALID_PARAMETER;
6464 /* Open the src file for reading. */
6465 status = SMB_VFS_CREATE_FILE(
6468 0, /* root_dir_fid */
6469 smb_fname_src, /* fname */
6470 FILE_GENERIC_READ, /* access_mask */
6471 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6472 FILE_OPEN, /* create_disposition*/
6473 0, /* create_options */
6474 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6475 INTERNAL_OPEN_ONLY, /* oplock_request */
6476 0, /* allocation_size */
6482 if (!NT_STATUS_IS_OK(status)) {
6486 status = get_full_smb_filename(talloc_tos(), smb_fname_src, &fname_src);
6487 if (!NT_STATUS_IS_OK(status)) {
6491 dosattrs = dos_mode(conn, fname_src, &smb_fname_src->st);
6493 TALLOC_FREE(fname_src);
6495 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6496 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6499 /* Open the dst file for writing. */
6500 status = SMB_VFS_CREATE_FILE(
6503 0, /* root_dir_fid */
6504 smb_fname_dst, /* fname */
6505 FILE_GENERIC_WRITE, /* access_mask */
6506 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6507 new_create_disposition, /* create_disposition*/
6508 0, /* create_options */
6509 dosattrs, /* file_attributes */
6510 INTERNAL_OPEN_ONLY, /* oplock_request */
6511 0, /* allocation_size */
6517 if (!NT_STATUS_IS_OK(status)) {
6518 close_file(NULL, fsp1, ERROR_CLOSE);
6522 if ((ofun&3) == 1) {
6523 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6524 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6526 * Stop the copy from occurring.
6529 smb_fname_src->st.st_ex_size = 0;
6533 /* Do the actual copy. */
6534 if (smb_fname_src->st.st_ex_size) {
6535 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6538 close_file(NULL, fsp1, NORMAL_CLOSE);
6540 /* Ensure the modtime is set correctly on the destination file. */
6541 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6544 * As we are opening fsp1 read-only we only expect
6545 * an error on close on fsp2 if we are out of space.
6546 * Thus we don't look at the error return from the
6549 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6551 if (!NT_STATUS_IS_OK(status)) {
6555 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6556 status = NT_STATUS_DISK_FULL;
6560 status = NT_STATUS_OK;
6563 TALLOC_FREE(smb_fname_dst_tmp);
6567 /****************************************************************************
6568 Reply to a file copy.
6569 ****************************************************************************/
6571 void reply_copy(struct smb_request *req)
6573 connection_struct *conn = req->conn;
6574 struct smb_filename *smb_fname_src = NULL;
6575 struct smb_filename *smb_fname_dst = NULL;
6576 char *fname_src = NULL;
6577 char *fname_dst = NULL;
6578 char *fname_src_mask = NULL;
6579 char *fname_src_dir = NULL;
6582 int error = ERRnoaccess;
6587 bool target_is_directory=False;
6588 bool source_has_wild = False;
6589 bool dest_has_wild = False;
6591 TALLOC_CTX *ctx = talloc_tos();
6593 START_PROFILE(SMBcopy);
6596 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6600 tid2 = SVAL(req->vwv+0, 0);
6601 ofun = SVAL(req->vwv+1, 0);
6602 flags = SVAL(req->vwv+2, 0);
6604 p = (const char *)req->buf;
6605 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6606 &status, &source_has_wild);
6607 if (!NT_STATUS_IS_OK(status)) {
6608 reply_nterror(req, status);
6611 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6612 &status, &dest_has_wild);
6613 if (!NT_STATUS_IS_OK(status)) {
6614 reply_nterror(req, status);
6618 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6620 if (tid2 != conn->cnum) {
6621 /* can't currently handle inter share copies XXXX */
6622 DEBUG(3,("Rejecting inter-share copy\n"));
6623 reply_doserror(req, ERRSRV, ERRinvdevice);
6627 status = resolve_dfspath_wcard(ctx, conn,
6628 req->flags2 & FLAGS2_DFS_PATHNAMES,
6632 if (!NT_STATUS_IS_OK(status)) {
6633 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6634 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6635 ERRSRV, ERRbadpath);
6638 reply_nterror(req, status);
6642 status = resolve_dfspath_wcard(ctx, conn,
6643 req->flags2 & FLAGS2_DFS_PATHNAMES,
6647 if (!NT_STATUS_IS_OK(status)) {
6648 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6649 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6650 ERRSRV, ERRbadpath);
6653 reply_nterror(req, status);
6657 status = unix_convert(ctx, conn, fname_src, &smb_fname_src,
6658 source_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6659 if (!NT_STATUS_IS_OK(status)) {
6660 reply_nterror(req, status);
6664 status = unix_convert(ctx, conn, fname_dst, &smb_fname_dst,
6665 dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6666 if (!NT_STATUS_IS_OK(status)) {
6667 reply_nterror(req, status);
6671 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->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_src->st)) {
6684 /* wants a tree copy! XXXX */
6685 DEBUG(3,("Rejecting tree copy\n"));
6686 reply_doserror(req, ERRSRV, ERRerror);
6690 /* Split up the directory from the filename/mask. */
6691 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6692 &fname_src_dir, &fname_src_mask);
6693 if (!NT_STATUS_IS_OK(status)) {
6694 reply_nterror(req, NT_STATUS_NO_MEMORY);
6699 * We should only check the mangled cache
6700 * here if unix_convert failed. This means
6701 * that the path in 'mask' doesn't exist
6702 * on the file system and so we need to look
6703 * for a possible mangle. This patch from
6704 * Tine Smukavec <valentin.smukavec@hermes.si>.
6706 if (!VALID_STAT(smb_fname_src->st) &&
6707 mangle_is_mangled(fname_src_mask, conn->params)) {
6708 char *new_mask = NULL;
6709 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6710 &new_mask, conn->params);
6712 /* Use demangled name if one was successfully found. */
6714 TALLOC_FREE(fname_src_mask);
6715 fname_src_mask = new_mask;
6719 if (!source_has_wild) {
6722 * Only one file needs to be copied. Append the mask back onto
6725 TALLOC_FREE(smb_fname_src->base_name);
6726 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6730 if (!smb_fname_src->base_name) {
6731 reply_nterror(req, NT_STATUS_NO_MEMORY);
6735 if (dest_has_wild) {
6736 char *fname_dst_mod = NULL;
6737 if (!resolve_wildcards(smb_fname_dst,
6738 smb_fname_src->base_name,
6739 smb_fname_dst->base_name,
6741 reply_nterror(req, NT_STATUS_NO_MEMORY);
6744 TALLOC_FREE(smb_fname_dst->base_name);
6745 smb_fname_dst->base_name = fname_dst_mod;
6748 status = check_name(conn, smb_fname_src->base_name);
6749 if (!NT_STATUS_IS_OK(status)) {
6750 reply_nterror(req, status);
6754 status = check_name(conn, smb_fname_dst->base_name);
6755 if (!NT_STATUS_IS_OK(status)) {
6756 reply_nterror(req, status);
6760 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6761 ofun, count, target_is_directory);
6763 if(!NT_STATUS_IS_OK(status)) {
6764 reply_nterror(req, status);
6770 struct smb_Dir *dir_hnd = NULL;
6771 const char *dname = NULL;
6775 * There is a wildcard that requires us to actually read the
6776 * src dir and copy each file matching the mask to the dst.
6777 * Right now streams won't be copied, but this could
6778 * presumably be added with a nested loop for reach dir entry.
6780 SMB_ASSERT(!smb_fname_src->stream_name);
6781 SMB_ASSERT(!smb_fname_dst->stream_name);
6783 smb_fname_src->stream_name = NULL;
6784 smb_fname_dst->stream_name = NULL;
6786 if (strequal(fname_src_mask,"????????.???")) {
6787 TALLOC_FREE(fname_src_mask);
6788 fname_src_mask = talloc_strdup(ctx, "*");
6789 if (!fname_src_mask) {
6790 reply_nterror(req, NT_STATUS_NO_MEMORY);
6795 status = check_name(conn, fname_src_dir);
6796 if (!NT_STATUS_IS_OK(status)) {
6797 reply_nterror(req, status);
6801 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6802 if (dir_hnd == NULL) {
6803 status = map_nt_error_from_unix(errno);
6804 reply_nterror(req, status);
6810 /* Iterate over the src dir copying each entry to the dst. */
6811 while ((dname = ReadDirName(dir_hnd, &offset,
6812 &smb_fname_src->st))) {
6813 char *destname = NULL;
6815 if (ISDOT(dname) || ISDOTDOT(dname)) {
6819 if (!is_visible_file(conn, fname_src_dir, dname,
6820 &smb_fname_src->st, false)) {
6824 if(!mask_match(dname, fname_src_mask,
6825 conn->case_sensitive)) {
6829 error = ERRnoaccess;
6831 /* Get the src smb_fname struct setup. */
6832 TALLOC_FREE(smb_fname_src->base_name);
6833 smb_fname_src->base_name =
6834 talloc_asprintf(smb_fname_src, "%s/%s",
6835 fname_src_dir, dname);
6837 if (!smb_fname_src->base_name) {
6838 TALLOC_FREE(dir_hnd);
6839 reply_nterror(req, NT_STATUS_NO_MEMORY);
6843 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6844 smb_fname_dst->base_name,
6849 TALLOC_FREE(dir_hnd);
6850 reply_nterror(req, NT_STATUS_NO_MEMORY);
6854 TALLOC_FREE(smb_fname_dst->base_name);
6855 smb_fname_dst->base_name = destname;
6857 status = check_name(conn, smb_fname_src->base_name);
6858 if (!NT_STATUS_IS_OK(status)) {
6859 TALLOC_FREE(dir_hnd);
6860 reply_nterror(req, status);
6864 status = check_name(conn, smb_fname_dst->base_name);
6865 if (!NT_STATUS_IS_OK(status)) {
6866 TALLOC_FREE(dir_hnd);
6867 reply_nterror(req, status);
6871 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
6872 smb_fname_src->base_name,
6873 smb_fname_dst->base_name));
6875 status = copy_file(ctx, conn, smb_fname_src,
6876 smb_fname_dst, ofun, count,
6877 target_is_directory);
6878 if (NT_STATUS_IS_OK(status)) {
6882 TALLOC_FREE(dir_hnd);
6887 /* Error on close... */
6889 reply_unixerror(req, ERRHRD, ERRgeneral);
6893 reply_doserror(req, ERRDOS, error);
6897 reply_outbuf(req, 1, 0);
6898 SSVAL(req->outbuf,smb_vwv0,count);
6900 TALLOC_FREE(smb_fname_src);
6901 TALLOC_FREE(smb_fname_dst);
6902 TALLOC_FREE(fname_src);
6903 TALLOC_FREE(fname_dst);
6904 TALLOC_FREE(fname_src_mask);
6905 TALLOC_FREE(fname_src_dir);
6907 END_PROFILE(SMBcopy);
6912 #define DBGC_CLASS DBGC_LOCKING
6914 /****************************************************************************
6915 Get a lock pid, dealing with large count requests.
6916 ****************************************************************************/
6918 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6919 bool large_file_format)
6921 if(!large_file_format)
6922 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6924 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6927 /****************************************************************************
6928 Get a lock count, dealing with large count requests.
6929 ****************************************************************************/
6931 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6932 bool large_file_format)
6936 if(!large_file_format) {
6937 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6940 #if defined(HAVE_LONGLONG)
6941 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6942 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6943 #else /* HAVE_LONGLONG */
6946 * NT4.x seems to be broken in that it sends large file (64 bit)
6947 * lockingX calls even if the CAP_LARGE_FILES was *not*
6948 * negotiated. For boxes without large unsigned ints truncate the
6949 * lock count by dropping the top 32 bits.
6952 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6953 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6954 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6955 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6956 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6959 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6960 #endif /* HAVE_LONGLONG */
6966 #if !defined(HAVE_LONGLONG)
6967 /****************************************************************************
6968 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6969 ****************************************************************************/
6971 static uint32 map_lock_offset(uint32 high, uint32 low)
6975 uint32 highcopy = high;
6978 * Try and find out how many significant bits there are in high.
6981 for(i = 0; highcopy; i++)
6985 * We use 31 bits not 32 here as POSIX
6986 * lock offsets may not be negative.
6989 mask = (~0) << (31 - i);
6992 return 0; /* Fail. */
6998 #endif /* !defined(HAVE_LONGLONG) */
7000 /****************************************************************************
7001 Get a lock offset, dealing with large offset requests.
7002 ****************************************************************************/
7004 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7005 bool large_file_format, bool *err)
7007 uint64_t offset = 0;
7011 if(!large_file_format) {
7012 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7015 #if defined(HAVE_LONGLONG)
7016 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7017 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7018 #else /* HAVE_LONGLONG */
7021 * NT4.x seems to be broken in that it sends large file (64 bit)
7022 * lockingX calls even if the CAP_LARGE_FILES was *not*
7023 * negotiated. For boxes without large unsigned ints mangle the
7024 * lock offset by mapping the top 32 bits onto the lower 32.
7027 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7028 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7029 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7032 if((new_low = map_lock_offset(high, low)) == 0) {
7034 return (uint64_t)-1;
7037 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7038 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7039 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7040 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7043 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7044 #endif /* HAVE_LONGLONG */
7050 /****************************************************************************
7051 Reply to a lockingX request.
7052 ****************************************************************************/
7054 void reply_lockingX(struct smb_request *req)
7056 connection_struct *conn = req->conn;
7058 unsigned char locktype;
7059 unsigned char oplocklevel;
7062 uint64_t count = 0, offset = 0;
7066 const uint8_t *data;
7067 bool large_file_format;
7069 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7071 START_PROFILE(SMBlockingX);
7074 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7075 END_PROFILE(SMBlockingX);
7079 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7080 locktype = CVAL(req->vwv+3, 0);
7081 oplocklevel = CVAL(req->vwv+3, 1);
7082 num_ulocks = SVAL(req->vwv+6, 0);
7083 num_locks = SVAL(req->vwv+7, 0);
7084 lock_timeout = IVAL(req->vwv+4, 0);
7085 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7087 if (!check_fsp(conn, req, fsp)) {
7088 END_PROFILE(SMBlockingX);
7094 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7095 /* we don't support these - and CANCEL_LOCK makes w2k
7096 and XP reboot so I don't really want to be
7097 compatible! (tridge) */
7098 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7099 END_PROFILE(SMBlockingX);
7103 /* Check if this is an oplock break on a file
7104 we have granted an oplock on.
7106 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7107 /* Client can insist on breaking to none. */
7108 bool break_to_none = (oplocklevel == 0);
7111 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7112 "for fnum = %d\n", (unsigned int)oplocklevel,
7116 * Make sure we have granted an exclusive or batch oplock on
7120 if (fsp->oplock_type == 0) {
7122 /* The Samba4 nbench simulator doesn't understand
7123 the difference between break to level2 and break
7124 to none from level2 - it sends oplock break
7125 replies in both cases. Don't keep logging an error
7126 message here - just ignore it. JRA. */
7128 DEBUG(5,("reply_lockingX: Error : oplock break from "
7129 "client for fnum = %d (oplock=%d) and no "
7130 "oplock granted on this file (%s).\n",
7131 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
7133 /* if this is a pure oplock break request then don't
7135 if (num_locks == 0 && num_ulocks == 0) {
7136 END_PROFILE(SMBlockingX);
7139 END_PROFILE(SMBlockingX);
7140 reply_doserror(req, ERRDOS, ERRlock);
7145 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7147 result = remove_oplock(fsp);
7149 result = downgrade_oplock(fsp);
7153 DEBUG(0, ("reply_lockingX: error in removing "
7154 "oplock on file %s\n", fsp->fsp_name));
7155 /* Hmmm. Is this panic justified? */
7156 smb_panic("internal tdb error");
7159 reply_to_oplock_break_requests(fsp);
7161 /* if this is a pure oplock break request then don't send a
7163 if (num_locks == 0 && num_ulocks == 0) {
7164 /* Sanity check - ensure a pure oplock break is not a
7166 if(CVAL(req->vwv+0, 0) != 0xff)
7167 DEBUG(0,("reply_lockingX: Error : pure oplock "
7168 "break is a chained %d request !\n",
7169 (unsigned int)CVAL(req->vwv+0, 0)));
7170 END_PROFILE(SMBlockingX);
7176 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7177 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7178 END_PROFILE(SMBlockingX);
7182 /* Data now points at the beginning of the list
7183 of smb_unlkrng structs */
7184 for(i = 0; i < (int)num_ulocks; i++) {
7185 lock_pid = get_lock_pid( data, i, large_file_format);
7186 count = get_lock_count( data, i, large_file_format);
7187 offset = get_lock_offset( data, i, large_file_format, &err);
7190 * There is no error code marked "stupid client bug".... :-).
7193 END_PROFILE(SMBlockingX);
7194 reply_doserror(req, ERRDOS, ERRnoaccess);
7198 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
7199 "pid %u, file %s\n", (double)offset, (double)count,
7200 (unsigned int)lock_pid, fsp->fsp_name ));
7202 status = do_unlock(smbd_messaging_context(),
7209 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
7210 nt_errstr(status)));
7212 if (NT_STATUS_V(status)) {
7213 END_PROFILE(SMBlockingX);
7214 reply_nterror(req, status);
7219 /* Setup the timeout in seconds. */
7221 if (!lp_blocking_locks(SNUM(conn))) {
7225 /* Now do any requested locks */
7226 data += ((large_file_format ? 20 : 10)*num_ulocks);
7228 /* Data now points at the beginning of the list
7229 of smb_lkrng structs */
7231 for(i = 0; i < (int)num_locks; i++) {
7232 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
7233 READ_LOCK:WRITE_LOCK);
7234 lock_pid = get_lock_pid( data, i, large_file_format);
7235 count = get_lock_count( data, i, large_file_format);
7236 offset = get_lock_offset( data, i, large_file_format, &err);
7239 * There is no error code marked "stupid client bug".... :-).
7242 END_PROFILE(SMBlockingX);
7243 reply_doserror(req, ERRDOS, ERRnoaccess);
7247 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
7248 "%u, file %s timeout = %d\n", (double)offset,
7249 (double)count, (unsigned int)lock_pid,
7250 fsp->fsp_name, (int)lock_timeout ));
7252 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7253 struct blocking_lock_record *blr = NULL;
7255 if (lp_blocking_locks(SNUM(conn))) {
7257 /* Schedule a message to ourselves to
7258 remove the blocking lock record and
7259 return the right error. */
7261 blr = blocking_lock_cancel(fsp,
7267 NT_STATUS_FILE_LOCK_CONFLICT);
7269 END_PROFILE(SMBlockingX);
7274 ERRcancelviolation));
7278 /* Remove a matching pending lock. */
7279 status = do_lock_cancel(fsp,
7286 bool blocking_lock = lock_timeout ? True : False;
7287 bool defer_lock = False;
7288 struct byte_range_lock *br_lck;
7289 uint32 block_smbpid;
7291 br_lck = do_lock(smbd_messaging_context(),
7303 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7304 /* Windows internal resolution for blocking locks seems
7305 to be about 200ms... Don't wait for less than that. JRA. */
7306 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7307 lock_timeout = lp_lock_spin_time();
7312 /* This heuristic seems to match W2K3 very well. If a
7313 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7314 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7315 far as I can tell. Replacement for do_lock_spin(). JRA. */
7317 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7318 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7320 lock_timeout = lp_lock_spin_time();
7323 if (br_lck && defer_lock) {
7325 * A blocking lock was requested. Package up
7326 * this smb into a queued request and push it
7327 * onto the blocking lock queue.
7329 if(push_blocking_lock_request(br_lck,
7340 TALLOC_FREE(br_lck);
7341 END_PROFILE(SMBlockingX);
7346 TALLOC_FREE(br_lck);
7349 if (NT_STATUS_V(status)) {
7350 END_PROFILE(SMBlockingX);
7351 reply_nterror(req, status);
7356 /* If any of the above locks failed, then we must unlock
7357 all of the previous locks (X/Open spec). */
7359 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7363 * Ensure we don't do a remove on the lock that just failed,
7364 * as under POSIX rules, if we have a lock already there, we
7365 * will delete it (and we shouldn't) .....
7367 for(i--; i >= 0; i--) {
7368 lock_pid = get_lock_pid( data, i, large_file_format);
7369 count = get_lock_count( data, i, large_file_format);
7370 offset = get_lock_offset( data, i, large_file_format,
7374 * There is no error code marked "stupid client
7378 END_PROFILE(SMBlockingX);
7379 reply_doserror(req, ERRDOS, ERRnoaccess);
7383 do_unlock(smbd_messaging_context(),
7390 END_PROFILE(SMBlockingX);
7391 reply_nterror(req, status);
7395 reply_outbuf(req, 2, 0);
7397 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7398 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7400 END_PROFILE(SMBlockingX);
7405 #define DBGC_CLASS DBGC_ALL
7407 /****************************************************************************
7408 Reply to a SMBreadbmpx (read block multiplex) request.
7409 Always reply with an error, if someone has a platform really needs this,
7410 please contact vl@samba.org
7411 ****************************************************************************/
7413 void reply_readbmpx(struct smb_request *req)
7415 START_PROFILE(SMBreadBmpx);
7416 reply_doserror(req, ERRSRV, ERRuseSTD);
7417 END_PROFILE(SMBreadBmpx);
7421 /****************************************************************************
7422 Reply to a SMBreadbs (read block multiplex secondary) request.
7423 Always reply with an error, if someone has a platform really needs this,
7424 please contact vl@samba.org
7425 ****************************************************************************/
7427 void reply_readbs(struct smb_request *req)
7429 START_PROFILE(SMBreadBs);
7430 reply_doserror(req, ERRSRV, ERRuseSTD);
7431 END_PROFILE(SMBreadBs);
7435 /****************************************************************************
7436 Reply to a SMBsetattrE.
7437 ****************************************************************************/
7439 void reply_setattrE(struct smb_request *req)
7441 connection_struct *conn = req->conn;
7442 struct smb_file_time ft;
7444 SMB_STRUCT_STAT sbuf;
7447 START_PROFILE(SMBsetattrE);
7451 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7452 END_PROFILE(SMBsetattrE);
7456 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7458 if(!fsp || (fsp->conn != conn)) {
7459 reply_doserror(req, ERRDOS, ERRbadfid);
7460 END_PROFILE(SMBsetattrE);
7466 * Convert the DOS times into unix times.
7469 ft.atime = convert_time_t_to_timespec(
7470 srv_make_unix_date2(req->vwv+3));
7471 ft.mtime = convert_time_t_to_timespec(
7472 srv_make_unix_date2(req->vwv+5));
7473 ft.create_time = convert_time_t_to_timespec(
7474 srv_make_unix_date2(req->vwv+1));
7476 reply_outbuf(req, 0, 0);
7479 * Patch from Ray Frush <frush@engr.colostate.edu>
7480 * Sometimes times are sent as zero - ignore them.
7483 /* Ensure we have a valid stat struct for the source. */
7484 if (fsp->fh->fd != -1) {
7485 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7486 status = map_nt_error_from_unix(errno);
7487 reply_nterror(req, status);
7488 END_PROFILE(SMBsetattrE);
7494 if (fsp->posix_open) {
7495 ret = vfs_lstat_smb_fname(conn, fsp->fsp_name, &sbuf);
7497 ret = vfs_stat_smb_fname(conn, fsp->fsp_name, &sbuf);
7500 status = map_nt_error_from_unix(errno);
7501 reply_nterror(req, status);
7502 END_PROFILE(SMBsetattrE);
7507 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7509 if (!NT_STATUS_IS_OK(status)) {
7510 reply_doserror(req, ERRDOS, ERRnoaccess);
7511 END_PROFILE(SMBsetattrE);
7515 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7518 (unsigned int)ft.atime.tv_sec,
7519 (unsigned int)ft.mtime.tv_sec,
7520 (unsigned int)ft.create_time.tv_sec
7523 END_PROFILE(SMBsetattrE);
7528 /* Back from the dead for OS/2..... JRA. */
7530 /****************************************************************************
7531 Reply to a SMBwritebmpx (write block multiplex primary) request.
7532 Always reply with an error, if someone has a platform really needs this,
7533 please contact vl@samba.org
7534 ****************************************************************************/
7536 void reply_writebmpx(struct smb_request *req)
7538 START_PROFILE(SMBwriteBmpx);
7539 reply_doserror(req, ERRSRV, ERRuseSTD);
7540 END_PROFILE(SMBwriteBmpx);
7544 /****************************************************************************
7545 Reply to a SMBwritebs (write block multiplex secondary) request.
7546 Always reply with an error, if someone has a platform really needs this,
7547 please contact vl@samba.org
7548 ****************************************************************************/
7550 void reply_writebs(struct smb_request *req)
7552 START_PROFILE(SMBwriteBs);
7553 reply_doserror(req, ERRSRV, ERRuseSTD);
7554 END_PROFILE(SMBwriteBs);
7558 /****************************************************************************
7559 Reply to a SMBgetattrE.
7560 ****************************************************************************/
7562 void reply_getattrE(struct smb_request *req)
7564 connection_struct *conn = req->conn;
7565 SMB_STRUCT_STAT sbuf;
7568 struct timespec create_ts;
7570 START_PROFILE(SMBgetattrE);
7573 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7574 END_PROFILE(SMBgetattrE);
7578 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7580 if(!fsp || (fsp->conn != conn)) {
7581 reply_doserror(req, ERRDOS, ERRbadfid);
7582 END_PROFILE(SMBgetattrE);
7586 /* Do an fstat on this file */
7587 if(fsp_stat(fsp, &sbuf)) {
7588 reply_unixerror(req, ERRDOS, ERRnoaccess);
7589 END_PROFILE(SMBgetattrE);
7593 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7596 * Convert the times into dos times. Set create
7597 * date to be last modify date as UNIX doesn't save
7601 reply_outbuf(req, 11, 0);
7603 create_ts = sbuf.st_ex_btime;
7604 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7605 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7606 convert_timespec_to_time_t(sbuf.st_ex_atime));
7607 /* Should we check pending modtime here ? JRA */
7608 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7609 convert_timespec_to_time_t(sbuf.st_ex_mtime));
7612 SIVAL(req->outbuf, smb_vwv6, 0);
7613 SIVAL(req->outbuf, smb_vwv8, 0);
7615 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7616 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_ex_size);
7617 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7619 SSVAL(req->outbuf,smb_vwv10, mode);
7621 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7623 END_PROFILE(SMBgetattrE);