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 (smb_fname->base_name[0] == '.' &&
1194 smb_fname->base_name[1] == '\0') {
1196 * Not sure here is the right place to catch this
1197 * condition. Might be moved to somewhere else later -- vl
1199 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1203 mode = SVAL(req->vwv+0, 0);
1204 mtime = srv_make_unix_date3(req->vwv+1);
1206 ft.mtime = convert_time_t_to_timespec(mtime);
1207 status = smb_set_file_time(conn, NULL, smb_fname, &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, smb_fname, mode, NULL,
1221 reply_unixerror(req, ERRDOS, ERRnoaccess);
1226 reply_outbuf(req, 0, 0);
1228 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1231 TALLOC_FREE(smb_fname);
1232 END_PROFILE(SMBsetatr);
1236 /****************************************************************************
1238 ****************************************************************************/
1240 void reply_dskattr(struct smb_request *req)
1242 connection_struct *conn = req->conn;
1243 uint64_t dfree,dsize,bsize;
1244 START_PROFILE(SMBdskattr);
1246 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1247 reply_unixerror(req, ERRHRD, ERRgeneral);
1248 END_PROFILE(SMBdskattr);
1252 reply_outbuf(req, 5, 0);
1254 if (Protocol <= PROTOCOL_LANMAN2) {
1255 double total_space, free_space;
1256 /* we need to scale this to a number that DOS6 can handle. We
1257 use floating point so we can handle large drives on systems
1258 that don't have 64 bit integers
1260 we end up displaying a maximum of 2G to DOS systems
1262 total_space = dsize * (double)bsize;
1263 free_space = dfree * (double)bsize;
1265 dsize = (uint64_t)((total_space+63*512) / (64*512));
1266 dfree = (uint64_t)((free_space+63*512) / (64*512));
1268 if (dsize > 0xFFFF) dsize = 0xFFFF;
1269 if (dfree > 0xFFFF) dfree = 0xFFFF;
1271 SSVAL(req->outbuf,smb_vwv0,dsize);
1272 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1273 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1274 SSVAL(req->outbuf,smb_vwv3,dfree);
1276 SSVAL(req->outbuf,smb_vwv0,dsize);
1277 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1278 SSVAL(req->outbuf,smb_vwv2,512);
1279 SSVAL(req->outbuf,smb_vwv3,dfree);
1282 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1284 END_PROFILE(SMBdskattr);
1289 * Utility function to split the filename from the directory.
1291 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1292 char **fname_dir_out,
1293 char **fname_mask_out)
1295 const char *p = NULL;
1296 char *fname_dir = NULL;
1297 char *fname_mask = NULL;
1299 p = strrchr_m(fname_in, '/');
1301 fname_dir = talloc_strdup(ctx, ".");
1302 fname_mask = talloc_strdup(ctx, fname_in);
1304 fname_dir = talloc_strndup(ctx, fname_in,
1305 PTR_DIFF(p, fname_in));
1306 fname_mask = talloc_strdup(ctx, p+1);
1309 if (!fname_dir || !fname_mask) {
1310 TALLOC_FREE(fname_dir);
1311 TALLOC_FREE(fname_mask);
1312 return NT_STATUS_NO_MEMORY;
1315 *fname_dir_out = fname_dir;
1316 *fname_mask_out = fname_mask;
1317 return NT_STATUS_OK;
1320 /****************************************************************************
1322 Can be called from SMBsearch, SMBffirst or SMBfunique.
1323 ****************************************************************************/
1325 void reply_search(struct smb_request *req)
1327 connection_struct *conn = req->conn;
1329 const char *mask = NULL;
1330 char *directory = NULL;
1334 struct timespec date;
1336 unsigned int numentries = 0;
1337 unsigned int maxentries = 0;
1338 bool finished = False;
1343 bool check_descend = False;
1344 bool expect_close = False;
1346 bool mask_contains_wcard = False;
1347 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1348 TALLOC_CTX *ctx = talloc_tos();
1349 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1351 START_PROFILE(SMBsearch);
1354 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1355 END_PROFILE(SMBsearch);
1359 if (lp_posix_pathnames()) {
1360 reply_unknown_new(req, req->cmd);
1361 END_PROFILE(SMBsearch);
1365 /* If we were called as SMBffirst then we must expect close. */
1366 if(req->cmd == SMBffirst) {
1367 expect_close = True;
1370 reply_outbuf(req, 1, 3);
1371 maxentries = SVAL(req->vwv+0, 0);
1372 dirtype = SVAL(req->vwv+1, 0);
1373 p = (const char *)req->buf + 1;
1374 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1375 &nt_status, &mask_contains_wcard);
1376 if (!NT_STATUS_IS_OK(nt_status)) {
1377 reply_nterror(req, nt_status);
1378 END_PROFILE(SMBsearch);
1383 status_len = SVAL(p, 0);
1386 /* dirtype &= ~aDIR; */
1388 if (status_len == 0) {
1389 struct smb_filename *smb_fname = NULL;
1391 nt_status = resolve_dfspath_wcard(ctx, conn,
1392 req->flags2 & FLAGS2_DFS_PATHNAMES,
1395 &mask_contains_wcard);
1396 if (!NT_STATUS_IS_OK(nt_status)) {
1397 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1398 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1399 ERRSRV, ERRbadpath);
1400 END_PROFILE(SMBsearch);
1403 reply_nterror(req, nt_status);
1404 END_PROFILE(SMBsearch);
1408 nt_status = unix_convert(ctx, conn, path, &smb_fname,
1409 UCF_ALLOW_WCARD_LCOMP);
1410 if (!NT_STATUS_IS_OK(nt_status)) {
1411 reply_nterror(req, nt_status);
1412 END_PROFILE(SMBsearch);
1416 nt_status = get_full_smb_filename(ctx, smb_fname, &directory);
1417 TALLOC_FREE(smb_fname);
1418 if (!NT_STATUS_IS_OK(nt_status)) {
1419 reply_nterror(req, nt_status);
1420 END_PROFILE(SMBsearch);
1424 nt_status = check_name(conn, directory);
1425 if (!NT_STATUS_IS_OK(nt_status)) {
1426 reply_nterror(req, nt_status);
1427 END_PROFILE(SMBsearch);
1431 p = strrchr_m(directory,'/');
1432 if ((p != NULL) && (*directory != '/')) {
1434 directory = talloc_strndup(ctx, directory,
1435 PTR_DIFF(p, directory));
1438 directory = talloc_strdup(ctx,".");
1442 reply_nterror(req, NT_STATUS_NO_MEMORY);
1443 END_PROFILE(SMBsearch);
1447 memset((char *)status,'\0',21);
1448 SCVAL(status,0,(dirtype & 0x1F));
1450 nt_status = dptr_create(conn,
1456 mask_contains_wcard,
1459 if (!NT_STATUS_IS_OK(nt_status)) {
1460 reply_nterror(req, nt_status);
1461 END_PROFILE(SMBsearch);
1464 dptr_num = dptr_dnum(conn->dirptr);
1468 memcpy(status,p,21);
1469 status_dirtype = CVAL(status,0) & 0x1F;
1470 if (status_dirtype != (dirtype & 0x1F)) {
1471 dirtype = status_dirtype;
1474 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1475 if (!conn->dirptr) {
1478 string_set(&conn->dirpath,dptr_path(dptr_num));
1479 mask = dptr_wcard(dptr_num);
1484 * For a 'continue' search we have no string. So
1485 * check from the initial saved string.
1487 mask_contains_wcard = ms_has_wild(mask);
1488 dirtype = dptr_attr(dptr_num);
1491 DEBUG(4,("dptr_num is %d\n",dptr_num));
1493 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1494 dptr_init_search_op(conn->dirptr);
1496 if ((dirtype&0x1F) == aVOLID) {
1497 char buf[DIR_STRUCT_SIZE];
1498 memcpy(buf,status,21);
1499 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1500 0,aVOLID,0,!allow_long_path_components)) {
1501 reply_nterror(req, NT_STATUS_NO_MEMORY);
1502 END_PROFILE(SMBsearch);
1505 dptr_fill(buf+12,dptr_num);
1506 if (dptr_zero(buf+12) && (status_len==0)) {
1511 if (message_push_blob(&req->outbuf,
1512 data_blob_const(buf, sizeof(buf)))
1514 reply_nterror(req, NT_STATUS_NO_MEMORY);
1515 END_PROFILE(SMBsearch);
1523 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1526 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1527 conn->dirpath,lp_dontdescend(SNUM(conn))));
1528 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1529 check_descend = True;
1532 for (i=numentries;(i<maxentries) && !finished;i++) {
1533 finished = !get_dir_entry(ctx,
1544 char buf[DIR_STRUCT_SIZE];
1545 memcpy(buf,status,21);
1546 if (!make_dir_struct(ctx,
1552 convert_timespec_to_time_t(date),
1553 !allow_long_path_components)) {
1554 reply_nterror(req, NT_STATUS_NO_MEMORY);
1555 END_PROFILE(SMBsearch);
1558 if (!dptr_fill(buf+12,dptr_num)) {
1561 if (message_push_blob(&req->outbuf,
1562 data_blob_const(buf, sizeof(buf)))
1564 reply_nterror(req, NT_STATUS_NO_MEMORY);
1565 END_PROFILE(SMBsearch);
1575 /* If we were called as SMBffirst with smb_search_id == NULL
1576 and no entries were found then return error and close dirptr
1579 if (numentries == 0) {
1580 dptr_close(&dptr_num);
1581 } else if(expect_close && status_len == 0) {
1582 /* Close the dptr - we know it's gone */
1583 dptr_close(&dptr_num);
1586 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1587 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1588 dptr_close(&dptr_num);
1591 if ((numentries == 0) && !mask_contains_wcard) {
1592 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1593 END_PROFILE(SMBsearch);
1597 SSVAL(req->outbuf,smb_vwv0,numentries);
1598 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1599 SCVAL(smb_buf(req->outbuf),0,5);
1600 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1602 /* The replies here are never long name. */
1603 SSVAL(req->outbuf, smb_flg2,
1604 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1605 if (!allow_long_path_components) {
1606 SSVAL(req->outbuf, smb_flg2,
1607 SVAL(req->outbuf, smb_flg2)
1608 & (~FLAGS2_LONG_PATH_COMPONENTS));
1611 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1612 SSVAL(req->outbuf, smb_flg2,
1613 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1616 directory = dptr_path(dptr_num);
1619 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1620 smb_fn_name(req->cmd),
1622 directory ? directory : "./",
1627 END_PROFILE(SMBsearch);
1631 /****************************************************************************
1632 Reply to a fclose (stop directory search).
1633 ****************************************************************************/
1635 void reply_fclose(struct smb_request *req)
1643 bool path_contains_wcard = False;
1644 TALLOC_CTX *ctx = talloc_tos();
1646 START_PROFILE(SMBfclose);
1648 if (lp_posix_pathnames()) {
1649 reply_unknown_new(req, req->cmd);
1650 END_PROFILE(SMBfclose);
1654 p = (const char *)req->buf + 1;
1655 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1656 &err, &path_contains_wcard);
1657 if (!NT_STATUS_IS_OK(err)) {
1658 reply_nterror(req, err);
1659 END_PROFILE(SMBfclose);
1663 status_len = SVAL(p,0);
1666 if (status_len == 0) {
1667 reply_doserror(req, ERRSRV, ERRsrverror);
1668 END_PROFILE(SMBfclose);
1672 memcpy(status,p,21);
1674 if(dptr_fetch(status+12,&dptr_num)) {
1675 /* Close the dptr - we know it's gone */
1676 dptr_close(&dptr_num);
1679 reply_outbuf(req, 1, 0);
1680 SSVAL(req->outbuf,smb_vwv0,0);
1682 DEBUG(3,("search close\n"));
1684 END_PROFILE(SMBfclose);
1688 /****************************************************************************
1690 ****************************************************************************/
1692 void reply_open(struct smb_request *req)
1694 connection_struct *conn = req->conn;
1695 struct smb_filename *smb_fname = NULL;
1707 uint32 create_disposition;
1708 uint32 create_options = 0;
1710 TALLOC_CTX *ctx = talloc_tos();
1712 START_PROFILE(SMBopen);
1715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1719 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1720 deny_mode = SVAL(req->vwv+0, 0);
1721 dos_attr = SVAL(req->vwv+1, 0);
1723 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1724 STR_TERMINATE, &status);
1725 if (!NT_STATUS_IS_OK(status)) {
1726 reply_nterror(req, status);
1730 status = filename_convert(ctx,
1732 req->flags2 & FLAGS2_DFS_PATHNAMES,
1736 if (!NT_STATUS_IS_OK(status)) {
1737 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1738 reply_botherror(req,
1739 NT_STATUS_PATH_NOT_COVERED,
1740 ERRSRV, ERRbadpath);
1743 reply_nterror(req, status);
1747 if (!map_open_params_to_ntcreate(
1748 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1749 &share_mode, &create_disposition, &create_options)) {
1750 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1754 status = SMB_VFS_CREATE_FILE(
1757 0, /* root_dir_fid */
1758 smb_fname, /* fname */
1759 access_mask, /* access_mask */
1760 share_mode, /* share_access */
1761 create_disposition, /* create_disposition*/
1762 create_options, /* create_options */
1763 dos_attr, /* file_attributes */
1764 oplock_request, /* oplock_request */
1765 0, /* allocation_size */
1771 if (!NT_STATUS_IS_OK(status)) {
1772 if (open_was_deferred(req->mid)) {
1773 /* We have re-scheduled this call. */
1776 reply_openerror(req, status);
1780 size = smb_fname->st.st_ex_size;
1781 fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st);
1782 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1785 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1786 close_file(req, fsp, ERROR_CLOSE);
1787 reply_doserror(req, ERRDOS,ERRnoaccess);
1791 reply_outbuf(req, 7, 0);
1792 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1793 SSVAL(req->outbuf,smb_vwv1,fattr);
1794 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1795 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1797 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1799 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1800 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1802 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1803 SCVAL(req->outbuf,smb_flg,
1804 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1807 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1808 SCVAL(req->outbuf,smb_flg,
1809 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1812 TALLOC_FREE(smb_fname);
1813 END_PROFILE(SMBopen);
1817 /****************************************************************************
1818 Reply to an open and X.
1819 ****************************************************************************/
1821 void reply_open_and_X(struct smb_request *req)
1823 connection_struct *conn = req->conn;
1824 struct smb_filename *smb_fname = NULL;
1829 /* Breakout the oplock request bits so we can set the
1830 reply bits separately. */
1831 int ex_oplock_request;
1832 int core_oplock_request;
1835 int smb_sattr = SVAL(req->vwv+4, 0);
1836 uint32 smb_time = make_unix_date3(req->vwv+6);
1844 uint64_t allocation_size;
1845 ssize_t retval = -1;
1848 uint32 create_disposition;
1849 uint32 create_options = 0;
1850 TALLOC_CTX *ctx = talloc_tos();
1852 START_PROFILE(SMBopenX);
1854 if (req->wct < 15) {
1855 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1859 open_flags = SVAL(req->vwv+2, 0);
1860 deny_mode = SVAL(req->vwv+3, 0);
1861 smb_attr = SVAL(req->vwv+5, 0);
1862 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1863 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1864 oplock_request = ex_oplock_request | core_oplock_request;
1865 smb_ofun = SVAL(req->vwv+8, 0);
1866 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1868 /* If it's an IPC, pass off the pipe handler. */
1870 if (lp_nt_pipe_support()) {
1871 reply_open_pipe_and_X(conn, req);
1873 reply_doserror(req, ERRSRV, ERRaccess);
1878 /* XXXX we need to handle passed times, sattr and flags */
1879 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1880 STR_TERMINATE, &status);
1881 if (!NT_STATUS_IS_OK(status)) {
1882 reply_nterror(req, status);
1886 status = filename_convert(ctx,
1888 req->flags2 & FLAGS2_DFS_PATHNAMES,
1892 if (!NT_STATUS_IS_OK(status)) {
1893 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1894 reply_botherror(req,
1895 NT_STATUS_PATH_NOT_COVERED,
1896 ERRSRV, ERRbadpath);
1899 reply_nterror(req, status);
1903 if (!map_open_params_to_ntcreate(
1904 fname, deny_mode, smb_ofun, &access_mask,
1905 &share_mode, &create_disposition, &create_options)) {
1906 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1910 status = SMB_VFS_CREATE_FILE(
1913 0, /* root_dir_fid */
1914 smb_fname, /* fname */
1915 access_mask, /* access_mask */
1916 share_mode, /* share_access */
1917 create_disposition, /* create_disposition*/
1918 create_options, /* create_options */
1919 smb_attr, /* file_attributes */
1920 oplock_request, /* oplock_request */
1921 0, /* allocation_size */
1925 &smb_action); /* pinfo */
1927 if (!NT_STATUS_IS_OK(status)) {
1928 if (open_was_deferred(req->mid)) {
1929 /* We have re-scheduled this call. */
1932 reply_openerror(req, status);
1936 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1937 if the file is truncated or created. */
1938 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1939 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1940 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1941 close_file(req, fsp, ERROR_CLOSE);
1942 reply_nterror(req, NT_STATUS_DISK_FULL);
1945 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1947 close_file(req, fsp, ERROR_CLOSE);
1948 reply_nterror(req, NT_STATUS_DISK_FULL);
1951 smb_fname->st.st_ex_size =
1952 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1955 fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st);
1956 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1958 close_file(req, fsp, ERROR_CLOSE);
1959 reply_doserror(req, ERRDOS, ERRnoaccess);
1963 /* If the caller set the extended oplock request bit
1964 and we granted one (by whatever means) - set the
1965 correct bit for extended oplock reply.
1968 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1969 smb_action |= EXTENDED_OPLOCK_GRANTED;
1972 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1973 smb_action |= EXTENDED_OPLOCK_GRANTED;
1976 /* If the caller set the core oplock request bit
1977 and we granted one (by whatever means) - set the
1978 correct bit for core oplock reply.
1981 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1982 reply_outbuf(req, 19, 0);
1984 reply_outbuf(req, 15, 0);
1987 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1988 SCVAL(req->outbuf, smb_flg,
1989 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1992 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1993 SCVAL(req->outbuf, smb_flg,
1994 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1997 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1998 SSVAL(req->outbuf,smb_vwv3,fattr);
1999 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2000 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2002 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2004 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2005 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2006 SSVAL(req->outbuf,smb_vwv11,smb_action);
2008 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2009 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2014 TALLOC_FREE(smb_fname);
2015 END_PROFILE(SMBopenX);
2019 /****************************************************************************
2020 Reply to a SMBulogoffX.
2021 ****************************************************************************/
2023 void reply_ulogoffX(struct smb_request *req)
2025 struct smbd_server_connection *sconn = smbd_server_conn;
2028 START_PROFILE(SMBulogoffX);
2030 vuser = get_valid_user_struct(sconn, req->vuid);
2033 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2037 /* in user level security we are supposed to close any files
2038 open by this user */
2039 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2040 file_close_user(req->vuid);
2043 invalidate_vuid(sconn, req->vuid);
2045 reply_outbuf(req, 2, 0);
2047 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2049 END_PROFILE(SMBulogoffX);
2053 /****************************************************************************
2054 Reply to a mknew or a create.
2055 ****************************************************************************/
2057 void reply_mknew(struct smb_request *req)
2059 connection_struct *conn = req->conn;
2060 struct smb_filename *smb_fname = NULL;
2063 struct smb_file_time ft;
2065 int oplock_request = 0;
2067 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2068 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2069 uint32 create_disposition;
2070 uint32 create_options = 0;
2071 TALLOC_CTX *ctx = talloc_tos();
2073 START_PROFILE(SMBcreate);
2077 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2081 fattr = SVAL(req->vwv+0, 0);
2082 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2085 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2087 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2088 STR_TERMINATE, &status);
2089 if (!NT_STATUS_IS_OK(status)) {
2090 reply_nterror(req, status);
2094 status = filename_convert(ctx,
2096 req->flags2 & FLAGS2_DFS_PATHNAMES,
2100 if (!NT_STATUS_IS_OK(status)) {
2101 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2102 reply_botherror(req,
2103 NT_STATUS_PATH_NOT_COVERED,
2104 ERRSRV, ERRbadpath);
2107 reply_nterror(req, status);
2111 if (fattr & aVOLID) {
2112 DEBUG(0,("Attempt to create file (%s) with volid set - "
2113 "please report this\n",
2114 smb_fname_str_dbg(smb_fname)));
2117 if(req->cmd == SMBmknew) {
2118 /* We should fail if file exists. */
2119 create_disposition = FILE_CREATE;
2121 /* Create if file doesn't exist, truncate if it does. */
2122 create_disposition = FILE_OVERWRITE_IF;
2125 status = SMB_VFS_CREATE_FILE(
2128 0, /* root_dir_fid */
2129 smb_fname, /* fname */
2130 access_mask, /* access_mask */
2131 share_mode, /* share_access */
2132 create_disposition, /* create_disposition*/
2133 create_options, /* create_options */
2134 fattr, /* file_attributes */
2135 oplock_request, /* oplock_request */
2136 0, /* allocation_size */
2142 if (!NT_STATUS_IS_OK(status)) {
2143 if (open_was_deferred(req->mid)) {
2144 /* We have re-scheduled this call. */
2147 reply_openerror(req, status);
2151 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2152 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2153 if (!NT_STATUS_IS_OK(status)) {
2154 END_PROFILE(SMBcreate);
2158 reply_outbuf(req, 1, 0);
2159 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2161 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2162 SCVAL(req->outbuf,smb_flg,
2163 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2166 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2167 SCVAL(req->outbuf,smb_flg,
2168 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2171 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2172 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2173 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2174 (unsigned int)fattr));
2177 TALLOC_FREE(smb_fname);
2178 END_PROFILE(SMBcreate);
2182 /****************************************************************************
2183 Reply to a create temporary file.
2184 ****************************************************************************/
2186 void reply_ctemp(struct smb_request *req)
2188 connection_struct *conn = req->conn;
2189 struct smb_filename *smb_fname = NULL;
2197 TALLOC_CTX *ctx = talloc_tos();
2199 START_PROFILE(SMBctemp);
2202 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2206 fattr = SVAL(req->vwv+0, 0);
2207 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2209 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2210 STR_TERMINATE, &status);
2211 if (!NT_STATUS_IS_OK(status)) {
2212 reply_nterror(req, status);
2216 fname = talloc_asprintf(ctx,
2220 fname = talloc_strdup(ctx, "TMXXXXXX");
2224 reply_nterror(req, NT_STATUS_NO_MEMORY);
2228 status = filename_convert(ctx, conn,
2229 req->flags2 & FLAGS2_DFS_PATHNAMES,
2233 if (!NT_STATUS_IS_OK(status)) {
2234 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2235 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2236 ERRSRV, ERRbadpath);
2239 reply_nterror(req, status);
2243 tmpfd = mkstemp(smb_fname->base_name);
2245 reply_unixerror(req, ERRDOS, ERRnoaccess);
2249 SMB_VFS_STAT(conn, smb_fname);
2251 /* We should fail if file does not exist. */
2252 status = SMB_VFS_CREATE_FILE(
2255 0, /* root_dir_fid */
2256 smb_fname, /* fname */
2257 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2258 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2259 FILE_OPEN, /* create_disposition*/
2260 0, /* create_options */
2261 fattr, /* file_attributes */
2262 oplock_request, /* oplock_request */
2263 0, /* allocation_size */
2269 /* close fd from mkstemp() */
2272 if (!NT_STATUS_IS_OK(status)) {
2273 if (open_was_deferred(req->mid)) {
2274 /* We have re-scheduled this call. */
2277 reply_openerror(req, status);
2281 reply_outbuf(req, 1, 0);
2282 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2284 /* the returned filename is relative to the directory */
2285 s = strrchr_m(fsp->fsp_name, '/');
2293 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2294 thing in the byte section. JRA */
2295 SSVALS(p, 0, -1); /* what is this? not in spec */
2297 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2299 reply_nterror(req, NT_STATUS_NO_MEMORY);
2303 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2304 SCVAL(req->outbuf, smb_flg,
2305 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2308 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2309 SCVAL(req->outbuf, smb_flg,
2310 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2313 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2314 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2315 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2317 TALLOC_FREE(smb_fname);
2318 END_PROFILE(SMBctemp);
2322 /*******************************************************************
2323 Check if a user is allowed to rename a file.
2324 ********************************************************************/
2326 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2327 uint16 dirtype, SMB_STRUCT_STAT *pst)
2331 if (!CAN_WRITE(conn)) {
2332 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2335 fmode = dos_mode(conn, fsp->fsp_name, pst);
2336 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2337 return NT_STATUS_NO_SUCH_FILE;
2340 if (S_ISDIR(pst->st_ex_mode)) {
2341 if (fsp->posix_open) {
2342 return NT_STATUS_OK;
2345 /* If no pathnames are open below this
2346 directory, allow the rename. */
2348 if (file_find_subpath(fsp)) {
2349 return NT_STATUS_ACCESS_DENIED;
2351 return NT_STATUS_OK;
2354 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2355 return NT_STATUS_OK;
2358 return NT_STATUS_ACCESS_DENIED;
2361 /*******************************************************************
2362 * unlink a file with all relevant access checks
2363 *******************************************************************/
2365 static NTSTATUS do_unlink(connection_struct *conn,
2366 struct smb_request *req,
2367 struct smb_filename *smb_fname,
2373 uint32 dirtype_orig = dirtype;
2376 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2378 if (!CAN_WRITE(conn)) {
2379 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2382 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
2383 return map_nt_error_from_unix(errno);
2386 status = get_full_smb_filename(smb_fname, smb_fname, &fname);
2387 if (!NT_STATUS_IS_OK(status)) {
2390 fattr = dos_mode(conn, fname, &smb_fname->st);
2393 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2394 dirtype = aDIR|aARCH|aRONLY;
2397 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2399 return NT_STATUS_NO_SUCH_FILE;
2402 if (!dir_check_ftype(conn, fattr, dirtype)) {
2404 return NT_STATUS_FILE_IS_A_DIRECTORY;
2406 return NT_STATUS_NO_SUCH_FILE;
2409 if (dirtype_orig & 0x8000) {
2410 /* These will never be set for POSIX. */
2411 return NT_STATUS_NO_SUCH_FILE;
2415 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2416 return NT_STATUS_FILE_IS_A_DIRECTORY;
2419 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2420 return NT_STATUS_NO_SUCH_FILE;
2423 if (dirtype & 0xFF00) {
2424 /* These will never be set for POSIX. */
2425 return NT_STATUS_NO_SUCH_FILE;
2430 return NT_STATUS_NO_SUCH_FILE;
2433 /* Can't delete a directory. */
2435 return NT_STATUS_FILE_IS_A_DIRECTORY;
2440 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2441 return NT_STATUS_OBJECT_NAME_INVALID;
2442 #endif /* JRATEST */
2444 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2446 On a Windows share, a file with read-only dosmode can be opened with
2447 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2448 fails with NT_STATUS_CANNOT_DELETE error.
2450 This semantic causes a problem that a user can not
2451 rename a file with read-only dosmode on a Samba share
2452 from a Windows command prompt (i.e. cmd.exe, but can rename
2453 from Windows Explorer).
2456 if (!lp_delete_readonly(SNUM(conn))) {
2457 if (fattr & aRONLY) {
2458 return NT_STATUS_CANNOT_DELETE;
2462 /* On open checks the open itself will check the share mode, so
2463 don't do it here as we'll get it wrong. */
2465 status = SMB_VFS_CREATE_FILE
2468 0, /* root_dir_fid */
2469 smb_fname, /* fname */
2470 DELETE_ACCESS, /* access_mask */
2471 FILE_SHARE_NONE, /* share_access */
2472 FILE_OPEN, /* create_disposition*/
2473 FILE_NON_DIRECTORY_FILE, /* create_options */
2474 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2475 0, /* oplock_request */
2476 0, /* allocation_size */
2482 if (!NT_STATUS_IS_OK(status)) {
2483 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2484 nt_errstr(status)));
2488 /* The set is across all open files on this dev/inode pair. */
2489 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2490 close_file(req, fsp, NORMAL_CLOSE);
2491 return NT_STATUS_ACCESS_DENIED;
2494 return close_file(req, fsp, NORMAL_CLOSE);
2497 /****************************************************************************
2498 The guts of the unlink command, split out so it may be called by the NT SMB
2500 ****************************************************************************/
2502 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2503 uint32 dirtype, const char *name_in, bool has_wild)
2505 struct smb_filename *smb_fname = NULL;
2506 char *fname_dir = NULL;
2507 char *fname_mask = NULL;
2509 NTSTATUS status = NT_STATUS_OK;
2510 TALLOC_CTX *ctx = talloc_tos();
2512 status = unix_convert(ctx, conn, name_in, &smb_fname,
2513 has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
2514 if (!NT_STATUS_IS_OK(status)) {
2518 /* Split up the directory from the filename/mask. */
2519 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2520 &fname_dir, &fname_mask);
2521 if (!NT_STATUS_IS_OK(status)) {
2526 * We should only check the mangled cache
2527 * here if unix_convert failed. This means
2528 * that the path in 'mask' doesn't exist
2529 * on the file system and so we need to look
2530 * for a possible mangle. This patch from
2531 * Tine Smukavec <valentin.smukavec@hermes.si>.
2534 if (!VALID_STAT(smb_fname->st) &&
2535 mangle_is_mangled(fname_mask, conn->params)) {
2536 char *new_mask = NULL;
2537 mangle_lookup_name_from_8_3(ctx, fname_mask,
2538 &new_mask, conn->params);
2540 TALLOC_FREE(fname_mask);
2541 fname_mask = new_mask;
2548 * Only one file needs to be unlinked. Append the mask back
2549 * onto the directory.
2551 TALLOC_FREE(smb_fname->base_name);
2552 smb_fname->base_name = talloc_asprintf(smb_fname,
2556 if (!smb_fname->base_name) {
2557 status = NT_STATUS_NO_MEMORY;
2561 dirtype = FILE_ATTRIBUTE_NORMAL;
2564 status = check_name(conn, smb_fname->base_name);
2565 if (!NT_STATUS_IS_OK(status)) {
2569 status = do_unlink(conn, req, smb_fname, dirtype);
2570 if (!NT_STATUS_IS_OK(status)) {
2576 struct smb_Dir *dir_hnd = NULL;
2580 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2581 status = NT_STATUS_OBJECT_NAME_INVALID;
2585 if (strequal(fname_mask,"????????.???")) {
2586 TALLOC_FREE(fname_mask);
2587 fname_mask = talloc_strdup(ctx, "*");
2589 status = NT_STATUS_NO_MEMORY;
2594 status = check_name(conn, fname_dir);
2595 if (!NT_STATUS_IS_OK(status)) {
2599 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2601 if (dir_hnd == NULL) {
2602 status = map_nt_error_from_unix(errno);
2606 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2607 the pattern matches against the long name, otherwise the short name
2608 We don't implement this yet XXXX
2611 status = NT_STATUS_NO_SUCH_FILE;
2613 while ((dname = ReadDirName(dir_hnd, &offset,
2615 if (!is_visible_file(conn, fname_dir, dname,
2616 &smb_fname->st, true)) {
2620 /* Quick check for "." and ".." */
2621 if (ISDOT(dname) || ISDOTDOT(dname)) {
2625 if(!mask_match(dname, fname_mask,
2626 conn->case_sensitive)) {
2630 TALLOC_FREE(smb_fname->base_name);
2631 smb_fname->base_name =
2632 talloc_asprintf(smb_fname, "%s/%s",
2635 if (!smb_fname->base_name) {
2636 TALLOC_FREE(dir_hnd);
2637 status = NT_STATUS_NO_MEMORY;
2641 status = check_name(conn, smb_fname->base_name);
2642 if (!NT_STATUS_IS_OK(status)) {
2643 TALLOC_FREE(dir_hnd);
2647 status = do_unlink(conn, req, smb_fname, dirtype);
2648 if (!NT_STATUS_IS_OK(status)) {
2653 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2654 smb_fname->base_name));
2656 TALLOC_FREE(dir_hnd);
2659 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2660 status = map_nt_error_from_unix(errno);
2664 TALLOC_FREE(smb_fname);
2665 TALLOC_FREE(fname_dir);
2666 TALLOC_FREE(fname_mask);
2670 /****************************************************************************
2672 ****************************************************************************/
2674 void reply_unlink(struct smb_request *req)
2676 connection_struct *conn = req->conn;
2680 bool path_contains_wcard = False;
2681 TALLOC_CTX *ctx = talloc_tos();
2683 START_PROFILE(SMBunlink);
2686 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2687 END_PROFILE(SMBunlink);
2691 dirtype = SVAL(req->vwv+0, 0);
2693 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2694 STR_TERMINATE, &status,
2695 &path_contains_wcard);
2696 if (!NT_STATUS_IS_OK(status)) {
2697 reply_nterror(req, status);
2698 END_PROFILE(SMBunlink);
2702 status = resolve_dfspath_wcard(ctx, conn,
2703 req->flags2 & FLAGS2_DFS_PATHNAMES,
2706 &path_contains_wcard);
2707 if (!NT_STATUS_IS_OK(status)) {
2708 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2709 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2710 ERRSRV, ERRbadpath);
2711 END_PROFILE(SMBunlink);
2714 reply_nterror(req, status);
2715 END_PROFILE(SMBunlink);
2719 DEBUG(3,("reply_unlink : %s\n",name));
2721 status = unlink_internals(conn, req, dirtype, name,
2722 path_contains_wcard);
2723 if (!NT_STATUS_IS_OK(status)) {
2724 if (open_was_deferred(req->mid)) {
2725 /* We have re-scheduled this call. */
2726 END_PROFILE(SMBunlink);
2729 reply_nterror(req, status);
2730 END_PROFILE(SMBunlink);
2734 reply_outbuf(req, 0, 0);
2735 END_PROFILE(SMBunlink);
2740 /****************************************************************************
2742 ****************************************************************************/
2744 static void fail_readraw(void)
2746 const char *errstr = talloc_asprintf(talloc_tos(),
2747 "FAIL ! reply_readbraw: socket write fail (%s)",
2752 exit_server_cleanly(errstr);
2755 /****************************************************************************
2756 Fake (read/write) sendfile. Returns -1 on read or write fail.
2757 ****************************************************************************/
2759 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2763 size_t tosend = nread;
2770 bufsize = MIN(nread, 65536);
2772 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2776 while (tosend > 0) {
2780 if (tosend > bufsize) {
2785 ret = read_file(fsp,buf,startpos,cur_read);
2791 /* If we had a short read, fill with zeros. */
2792 if (ret < cur_read) {
2793 memset(buf + ret, '\0', cur_read - ret);
2796 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2801 startpos += cur_read;
2805 return (ssize_t)nread;
2808 #if defined(WITH_SENDFILE)
2809 /****************************************************************************
2810 Deal with the case of sendfile reading less bytes from the file than
2811 requested. Fill with zeros (all we can do).
2812 ****************************************************************************/
2814 static void sendfile_short_send(files_struct *fsp,
2819 #define SHORT_SEND_BUFSIZE 1024
2820 if (nread < headersize) {
2821 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2822 "header for file %s (%s). Terminating\n",
2823 fsp->fsp_name, strerror(errno) ));
2824 exit_server_cleanly("sendfile_short_send failed");
2827 nread -= headersize;
2829 if (nread < smb_maxcnt) {
2830 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2832 exit_server_cleanly("sendfile_short_send: "
2836 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2837 "with zeros !\n", fsp->fsp_name));
2839 while (nread < smb_maxcnt) {
2841 * We asked for the real file size and told sendfile
2842 * to not go beyond the end of the file. But it can
2843 * happen that in between our fstat call and the
2844 * sendfile call the file was truncated. This is very
2845 * bad because we have already announced the larger
2846 * number of bytes to the client.
2848 * The best we can do now is to send 0-bytes, just as
2849 * a read from a hole in a sparse file would do.
2851 * This should happen rarely enough that I don't care
2852 * about efficiency here :-)
2856 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2857 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2858 exit_server_cleanly("sendfile_short_send: "
2859 "write_data failed");
2866 #endif /* defined WITH_SENDFILE */
2868 /****************************************************************************
2869 Return a readbraw error (4 bytes of zero).
2870 ****************************************************************************/
2872 static void reply_readbraw_error(void)
2876 if (write_data(smbd_server_fd(),header,4) != 4) {
2881 /****************************************************************************
2882 Use sendfile in readbraw.
2883 ****************************************************************************/
2885 static void send_file_readbraw(connection_struct *conn,
2886 struct smb_request *req,
2892 char *outbuf = NULL;
2895 #if defined(WITH_SENDFILE)
2897 * We can only use sendfile on a non-chained packet
2898 * but we can use on a non-oplocked file. tridge proved this
2899 * on a train in Germany :-). JRA.
2900 * reply_readbraw has already checked the length.
2903 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2904 (fsp->wcp == NULL) &&
2905 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2906 ssize_t sendfile_read = -1;
2908 DATA_BLOB header_blob;
2910 _smb_setlen(header,nread);
2911 header_blob = data_blob_const(header, 4);
2913 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2914 &header_blob, startpos, nread)) == -1) {
2915 /* Returning ENOSYS means no data at all was sent.
2916 * Do this as a normal read. */
2917 if (errno == ENOSYS) {
2918 goto normal_readbraw;
2922 * Special hack for broken Linux with no working sendfile. If we
2923 * return EINTR we sent the header but not the rest of the data.
2924 * Fake this up by doing read/write calls.
2926 if (errno == EINTR) {
2927 /* Ensure we don't do this again. */
2928 set_use_sendfile(SNUM(conn), False);
2929 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2931 if (fake_sendfile(fsp, startpos, nread) == -1) {
2932 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2933 fsp->fsp_name, strerror(errno) ));
2934 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2939 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2940 fsp->fsp_name, strerror(errno) ));
2941 exit_server_cleanly("send_file_readbraw sendfile failed");
2942 } else if (sendfile_read == 0) {
2944 * Some sendfile implementations return 0 to indicate
2945 * that there was a short read, but nothing was
2946 * actually written to the socket. In this case,
2947 * fallback to the normal read path so the header gets
2948 * the correct byte count.
2950 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2951 "bytes falling back to the normal read: "
2952 "%s\n", fsp->fsp_name));
2953 goto normal_readbraw;
2956 /* Deal with possible short send. */
2957 if (sendfile_read != 4+nread) {
2958 sendfile_short_send(fsp, sendfile_read, 4, nread);
2966 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2968 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2969 (unsigned)(nread+4)));
2970 reply_readbraw_error();
2975 ret = read_file(fsp,outbuf+4,startpos,nread);
2976 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2985 _smb_setlen(outbuf,ret);
2986 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2989 TALLOC_FREE(outbuf);
2992 /****************************************************************************
2993 Reply to a readbraw (core+ protocol).
2994 ****************************************************************************/
2996 void reply_readbraw(struct smb_request *req)
2998 connection_struct *conn = req->conn;
2999 ssize_t maxcount,mincount;
3003 struct lock_struct lock;
3007 START_PROFILE(SMBreadbraw);
3009 if (srv_is_signing_active(smbd_server_conn) ||
3010 is_encrypted_packet(req->inbuf)) {
3011 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3012 "raw reads/writes are disallowed.");
3016 reply_readbraw_error();
3017 END_PROFILE(SMBreadbraw);
3022 * Special check if an oplock break has been issued
3023 * and the readraw request croses on the wire, we must
3024 * return a zero length response here.
3027 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3030 * We have to do a check_fsp by hand here, as
3031 * we must always return 4 zero bytes on error,
3035 if (!fsp || !conn || conn != fsp->conn ||
3036 req->vuid != fsp->vuid ||
3037 fsp->is_directory || fsp->fh->fd == -1) {
3039 * fsp could be NULL here so use the value from the packet. JRA.
3041 DEBUG(3,("reply_readbraw: fnum %d not valid "
3043 (int)SVAL(req->vwv+0, 0)));
3044 reply_readbraw_error();
3045 END_PROFILE(SMBreadbraw);
3049 /* Do a "by hand" version of CHECK_READ. */
3050 if (!(fsp->can_read ||
3051 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3052 (fsp->access_mask & FILE_EXECUTE)))) {
3053 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3054 (int)SVAL(req->vwv+0, 0)));
3055 reply_readbraw_error();
3056 END_PROFILE(SMBreadbraw);
3060 flush_write_cache(fsp, READRAW_FLUSH);
3062 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3063 if(req->wct == 10) {
3065 * This is a large offset (64 bit) read.
3067 #ifdef LARGE_SMB_OFF_T
3069 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3071 #else /* !LARGE_SMB_OFF_T */
3074 * Ensure we haven't been sent a >32 bit offset.
3077 if(IVAL(req->vwv+8, 0) != 0) {
3078 DEBUG(0,("reply_readbraw: large offset "
3079 "(%x << 32) used and we don't support "
3080 "64 bit offsets.\n",
3081 (unsigned int)IVAL(req->vwv+8, 0) ));
3082 reply_readbraw_error();
3083 END_PROFILE(SMBreadbraw);
3087 #endif /* LARGE_SMB_OFF_T */
3090 DEBUG(0,("reply_readbraw: negative 64 bit "
3091 "readraw offset (%.0f) !\n",
3092 (double)startpos ));
3093 reply_readbraw_error();
3094 END_PROFILE(SMBreadbraw);
3099 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3100 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3102 /* ensure we don't overrun the packet size */
3103 maxcount = MIN(65535,maxcount);
3105 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3106 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3109 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3110 reply_readbraw_error();
3111 END_PROFILE(SMBreadbraw);
3115 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3116 size = st.st_ex_size;
3119 if (startpos >= size) {
3122 nread = MIN(maxcount,(size - startpos));
3125 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3126 if (nread < mincount)
3130 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3131 "min=%lu nread=%lu\n",
3132 fsp->fnum, (double)startpos,
3133 (unsigned long)maxcount,
3134 (unsigned long)mincount,
3135 (unsigned long)nread ) );
3137 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3139 DEBUG(5,("reply_readbraw finished\n"));
3141 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3143 END_PROFILE(SMBreadbraw);
3148 #define DBGC_CLASS DBGC_LOCKING
3150 /****************************************************************************
3151 Reply to a lockread (core+ protocol).
3152 ****************************************************************************/
3154 void reply_lockread(struct smb_request *req)
3156 connection_struct *conn = req->conn;
3163 struct byte_range_lock *br_lck = NULL;
3165 struct smbd_server_connection *sconn = smbd_server_conn;
3167 START_PROFILE(SMBlockread);
3170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3171 END_PROFILE(SMBlockread);
3175 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3177 if (!check_fsp(conn, req, fsp)) {
3178 END_PROFILE(SMBlockread);
3182 if (!CHECK_READ(fsp,req)) {
3183 reply_doserror(req, ERRDOS, ERRbadaccess);
3184 END_PROFILE(SMBlockread);
3188 numtoread = SVAL(req->vwv+1, 0);
3189 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3191 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3193 reply_outbuf(req, 5, numtoread + 3);
3195 data = smb_buf(req->outbuf) + 3;
3198 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3199 * protocol request that predates the read/write lock concept.
3200 * Thus instead of asking for a read lock here we need to ask
3201 * for a write lock. JRA.
3202 * Note that the requested lock size is unaffected by max_recv.
3205 br_lck = do_lock(smbd_messaging_context(),
3208 (uint64_t)numtoread,
3212 False, /* Non-blocking lock. */
3216 TALLOC_FREE(br_lck);
3218 if (NT_STATUS_V(status)) {
3219 reply_nterror(req, status);
3220 END_PROFILE(SMBlockread);
3225 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3228 if (numtoread > sconn->smb1.negprot.max_recv) {
3229 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3230 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3231 (unsigned int)numtoread,
3232 (unsigned int)sconn->smb1.negprot.max_recv));
3233 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3235 nread = read_file(fsp,data,startpos,numtoread);
3238 reply_unixerror(req, ERRDOS, ERRnoaccess);
3239 END_PROFILE(SMBlockread);
3243 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3245 SSVAL(req->outbuf,smb_vwv0,nread);
3246 SSVAL(req->outbuf,smb_vwv5,nread+3);
3247 p = smb_buf(req->outbuf);
3248 SCVAL(p,0,0); /* pad byte. */
3251 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3252 fsp->fnum, (int)numtoread, (int)nread));
3254 END_PROFILE(SMBlockread);
3259 #define DBGC_CLASS DBGC_ALL
3261 /****************************************************************************
3263 ****************************************************************************/
3265 void reply_read(struct smb_request *req)
3267 connection_struct *conn = req->conn;
3274 struct lock_struct lock;
3275 struct smbd_server_connection *sconn = smbd_server_conn;
3277 START_PROFILE(SMBread);
3280 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3281 END_PROFILE(SMBread);
3285 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3287 if (!check_fsp(conn, req, fsp)) {
3288 END_PROFILE(SMBread);
3292 if (!CHECK_READ(fsp,req)) {
3293 reply_doserror(req, ERRDOS, ERRbadaccess);
3294 END_PROFILE(SMBread);
3298 numtoread = SVAL(req->vwv+1, 0);
3299 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3301 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3304 * The requested read size cannot be greater than max_recv. JRA.
3306 if (numtoread > sconn->smb1.negprot.max_recv) {
3307 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3308 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3309 (unsigned int)numtoread,
3310 (unsigned int)sconn->smb1.negprot.max_recv));
3311 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3314 reply_outbuf(req, 5, numtoread+3);
3316 data = smb_buf(req->outbuf) + 3;
3318 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3319 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3322 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3323 reply_doserror(req, ERRDOS,ERRlock);
3324 END_PROFILE(SMBread);
3329 nread = read_file(fsp,data,startpos,numtoread);
3332 reply_unixerror(req, ERRDOS,ERRnoaccess);
3336 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3338 SSVAL(req->outbuf,smb_vwv0,nread);
3339 SSVAL(req->outbuf,smb_vwv5,nread+3);
3340 SCVAL(smb_buf(req->outbuf),0,1);
3341 SSVAL(smb_buf(req->outbuf),1,nread);
3343 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3344 fsp->fnum, (int)numtoread, (int)nread ) );
3347 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3349 END_PROFILE(SMBread);
3353 /****************************************************************************
3355 ****************************************************************************/
3357 static int setup_readX_header(struct smb_request *req, char *outbuf,
3363 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3364 data = smb_buf(outbuf);
3366 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3368 SCVAL(outbuf,smb_vwv0,0xFF);
3369 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3370 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3371 SSVAL(outbuf,smb_vwv6,
3373 + 1 /* the wct field */
3374 + 12 * sizeof(uint16_t) /* vwv */
3375 + 2); /* the buflen field */
3376 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3377 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3378 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3379 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3383 /****************************************************************************
3384 Reply to a read and X - possibly using sendfile.
3385 ****************************************************************************/
3387 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3388 files_struct *fsp, SMB_OFF_T startpos,
3391 SMB_STRUCT_STAT sbuf;
3393 struct lock_struct lock;
3395 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3396 reply_unixerror(req, ERRDOS, ERRnoaccess);
3400 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3401 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3404 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3405 reply_doserror(req, ERRDOS, ERRlock);
3409 if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
3410 || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
3412 * We already know that we would do a short read, so don't
3413 * try the sendfile() path.
3415 goto nosendfile_read;
3418 #if defined(WITH_SENDFILE)
3420 * We can only use sendfile on a non-chained packet
3421 * but we can use on a non-oplocked file. tridge proved this
3422 * on a train in Germany :-). JRA.
3425 if (!req_is_in_chain(req) &&
3426 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3427 (fsp->wcp == NULL) &&
3428 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3429 uint8 headerbuf[smb_size + 12 * 2];
3433 * Set up the packet header before send. We
3434 * assume here the sendfile will work (get the
3435 * correct amount of data).
3438 header = data_blob_const(headerbuf, sizeof(headerbuf));
3440 construct_reply_common_req(req, (char *)headerbuf);
3441 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3443 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3444 /* Returning ENOSYS means no data at all was sent.
3445 Do this as a normal read. */
3446 if (errno == ENOSYS) {
3451 * Special hack for broken Linux with no working sendfile. If we
3452 * return EINTR we sent the header but not the rest of the data.
3453 * Fake this up by doing read/write calls.
3456 if (errno == EINTR) {
3457 /* Ensure we don't do this again. */
3458 set_use_sendfile(SNUM(conn), False);
3459 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3460 nread = fake_sendfile(fsp, startpos,
3463 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3464 fsp->fsp_name, strerror(errno) ));
3465 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3467 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3468 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3469 /* No outbuf here means successful sendfile. */
3473 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3474 fsp->fsp_name, strerror(errno) ));
3475 exit_server_cleanly("send_file_readX sendfile failed");
3476 } else if (nread == 0) {
3478 * Some sendfile implementations return 0 to indicate
3479 * that there was a short read, but nothing was
3480 * actually written to the socket. In this case,
3481 * fallback to the normal read path so the header gets
3482 * the correct byte count.
3484 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3485 "falling back to the normal read: %s\n",
3490 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3491 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3493 /* Deal with possible short send. */
3494 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3495 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3497 /* No outbuf here means successful sendfile. */
3498 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3499 SMB_PERFCOUNT_END(&req->pcd);
3507 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3508 uint8 headerbuf[smb_size + 2*12];
3510 construct_reply_common_req(req, (char *)headerbuf);
3511 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3513 /* Send out the header. */
3514 if (write_data(smbd_server_fd(), (char *)headerbuf,
3515 sizeof(headerbuf)) != sizeof(headerbuf)) {
3516 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3517 fsp->fsp_name, strerror(errno) ));
3518 exit_server_cleanly("send_file_readX sendfile failed");
3520 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3522 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3523 fsp->fsp_name, strerror(errno) ));
3524 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3531 reply_outbuf(req, 12, smb_maxcnt);
3533 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3535 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3538 reply_unixerror(req, ERRDOS, ERRnoaccess);
3542 setup_readX_header(req, (char *)req->outbuf, nread);
3544 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3545 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3551 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3552 TALLOC_FREE(req->outbuf);
3556 /****************************************************************************
3557 Reply to a read and X.
3558 ****************************************************************************/
3560 void reply_read_and_X(struct smb_request *req)
3562 connection_struct *conn = req->conn;
3566 bool big_readX = False;
3568 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3571 START_PROFILE(SMBreadX);
3573 if ((req->wct != 10) && (req->wct != 12)) {
3574 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3578 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3579 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3580 smb_maxcnt = SVAL(req->vwv+5, 0);
3582 /* If it's an IPC, pass off the pipe handler. */
3584 reply_pipe_read_and_X(req);
3585 END_PROFILE(SMBreadX);
3589 if (!check_fsp(conn, req, fsp)) {
3590 END_PROFILE(SMBreadX);
3594 if (!CHECK_READ(fsp,req)) {
3595 reply_doserror(req, ERRDOS,ERRbadaccess);
3596 END_PROFILE(SMBreadX);
3600 if (global_client_caps & CAP_LARGE_READX) {
3601 size_t upper_size = SVAL(req->vwv+7, 0);
3602 smb_maxcnt |= (upper_size<<16);
3603 if (upper_size > 1) {
3604 /* Can't do this on a chained packet. */
3605 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3606 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3607 END_PROFILE(SMBreadX);
3610 /* We currently don't do this on signed or sealed data. */
3611 if (srv_is_signing_active(smbd_server_conn) ||
3612 is_encrypted_packet(req->inbuf)) {
3613 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3614 END_PROFILE(SMBreadX);
3617 /* Is there room in the reply for this data ? */
3618 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3620 NT_STATUS_INVALID_PARAMETER);
3621 END_PROFILE(SMBreadX);
3628 if (req->wct == 12) {
3629 #ifdef LARGE_SMB_OFF_T
3631 * This is a large offset (64 bit) read.
3633 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3635 #else /* !LARGE_SMB_OFF_T */
3638 * Ensure we haven't been sent a >32 bit offset.
3641 if(IVAL(req->vwv+10, 0) != 0) {
3642 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3643 "used and we don't support 64 bit offsets.\n",
3644 (unsigned int)IVAL(req->vwv+10, 0) ));
3645 END_PROFILE(SMBreadX);
3646 reply_doserror(req, ERRDOS, ERRbadaccess);
3650 #endif /* LARGE_SMB_OFF_T */
3655 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3659 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3662 END_PROFILE(SMBreadX);
3666 /****************************************************************************
3667 Error replies to writebraw must have smb_wct == 1. Fix this up.
3668 ****************************************************************************/
3670 void error_to_writebrawerr(struct smb_request *req)
3672 uint8 *old_outbuf = req->outbuf;
3674 reply_outbuf(req, 1, 0);
3676 memcpy(req->outbuf, old_outbuf, smb_size);
3677 TALLOC_FREE(old_outbuf);
3680 /****************************************************************************
3681 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3682 ****************************************************************************/
3684 void reply_writebraw(struct smb_request *req)
3686 connection_struct *conn = req->conn;
3689 ssize_t total_written=0;
3690 size_t numtowrite=0;
3696 struct lock_struct lock;
3699 START_PROFILE(SMBwritebraw);
3702 * If we ever reply with an error, it must have the SMB command
3703 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3706 SCVAL(req->inbuf,smb_com,SMBwritec);
3708 if (srv_is_signing_active(smbd_server_conn)) {
3709 END_PROFILE(SMBwritebraw);
3710 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3711 "raw reads/writes are disallowed.");
3714 if (req->wct < 12) {
3715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3716 error_to_writebrawerr(req);
3717 END_PROFILE(SMBwritebraw);
3721 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3722 if (!check_fsp(conn, req, fsp)) {
3723 error_to_writebrawerr(req);
3724 END_PROFILE(SMBwritebraw);
3728 if (!CHECK_WRITE(fsp)) {
3729 reply_doserror(req, ERRDOS, ERRbadaccess);
3730 error_to_writebrawerr(req);
3731 END_PROFILE(SMBwritebraw);
3735 tcount = IVAL(req->vwv+1, 0);
3736 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3737 write_through = BITSETW(req->vwv+7,0);
3739 /* We have to deal with slightly different formats depending
3740 on whether we are using the core+ or lanman1.0 protocol */
3742 if(Protocol <= PROTOCOL_COREPLUS) {
3743 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3744 data = smb_buf(req->inbuf);
3746 numtowrite = SVAL(req->vwv+10, 0);
3747 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3750 /* Ensure we don't write bytes past the end of this packet. */
3751 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3752 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3753 error_to_writebrawerr(req);
3754 END_PROFILE(SMBwritebraw);
3758 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3759 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3762 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3763 reply_doserror(req, ERRDOS, ERRlock);
3764 error_to_writebrawerr(req);
3765 END_PROFILE(SMBwritebraw);
3770 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3773 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3774 "wrote=%d sync=%d\n",
3775 fsp->fnum, (double)startpos, (int)numtowrite,
3776 (int)nwritten, (int)write_through));
3778 if (nwritten < (ssize_t)numtowrite) {
3779 reply_unixerror(req, ERRHRD, ERRdiskfull);
3780 error_to_writebrawerr(req);
3784 total_written = nwritten;
3786 /* Allocate a buffer of 64k + length. */
3787 buf = TALLOC_ARRAY(NULL, char, 65540);
3789 reply_doserror(req, ERRDOS, ERRnomem);
3790 error_to_writebrawerr(req);
3794 /* Return a SMBwritebraw message to the redirector to tell
3795 * it to send more bytes */
3797 memcpy(buf, req->inbuf, smb_size);
3798 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3799 SCVAL(buf,smb_com,SMBwritebraw);
3800 SSVALS(buf,smb_vwv0,0xFFFF);
3802 if (!srv_send_smb(smbd_server_fd(),
3804 false, 0, /* no signing */
3805 IS_CONN_ENCRYPTED(conn),
3807 exit_server_cleanly("reply_writebraw: srv_send_smb "
3811 /* Now read the raw data into the buffer and write it */
3812 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3814 if (!NT_STATUS_IS_OK(status)) {
3815 exit_server_cleanly("secondary writebraw failed");
3818 /* Set up outbuf to return the correct size */
3819 reply_outbuf(req, 1, 0);
3821 if (numtowrite != 0) {
3823 if (numtowrite > 0xFFFF) {
3824 DEBUG(0,("reply_writebraw: Oversize secondary write "
3825 "raw requested (%u). Terminating\n",
3826 (unsigned int)numtowrite ));
3827 exit_server_cleanly("secondary writebraw failed");
3830 if (tcount > nwritten+numtowrite) {
3831 DEBUG(3,("reply_writebraw: Client overestimated the "
3833 (int)tcount,(int)nwritten,(int)numtowrite));
3836 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3838 if (!NT_STATUS_IS_OK(status)) {
3839 DEBUG(0,("reply_writebraw: Oversize secondary write "
3840 "raw read failed (%s). Terminating\n",
3841 nt_errstr(status)));
3842 exit_server_cleanly("secondary writebraw failed");
3845 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3846 if (nwritten == -1) {
3848 reply_unixerror(req, ERRHRD, ERRdiskfull);
3849 error_to_writebrawerr(req);
3853 if (nwritten < (ssize_t)numtowrite) {
3854 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3855 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3859 total_written += nwritten;
3864 SSVAL(req->outbuf,smb_vwv0,total_written);
3866 status = sync_file(conn, fsp, write_through);
3867 if (!NT_STATUS_IS_OK(status)) {
3868 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3869 fsp->fsp_name, nt_errstr(status) ));
3870 reply_nterror(req, status);
3871 error_to_writebrawerr(req);
3875 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3877 fsp->fnum, (double)startpos, (int)numtowrite,
3878 (int)total_written));
3880 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3882 /* We won't return a status if write through is not selected - this
3883 * follows what WfWg does */
3884 END_PROFILE(SMBwritebraw);
3886 if (!write_through && total_written==tcount) {
3888 #if RABBIT_PELLET_FIX
3890 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3891 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3894 if (!send_keepalive(smbd_server_fd())) {
3895 exit_server_cleanly("reply_writebraw: send of "
3896 "keepalive failed");
3899 TALLOC_FREE(req->outbuf);
3904 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3906 END_PROFILE(SMBwritebraw);
3911 #define DBGC_CLASS DBGC_LOCKING
3913 /****************************************************************************
3914 Reply to a writeunlock (core+).
3915 ****************************************************************************/
3917 void reply_writeunlock(struct smb_request *req)
3919 connection_struct *conn = req->conn;
3920 ssize_t nwritten = -1;
3924 NTSTATUS status = NT_STATUS_OK;
3926 struct lock_struct lock;
3928 START_PROFILE(SMBwriteunlock);
3931 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3932 END_PROFILE(SMBwriteunlock);
3936 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3938 if (!check_fsp(conn, req, fsp)) {
3939 END_PROFILE(SMBwriteunlock);
3943 if (!CHECK_WRITE(fsp)) {
3944 reply_doserror(req, ERRDOS,ERRbadaccess);
3945 END_PROFILE(SMBwriteunlock);
3949 numtowrite = SVAL(req->vwv+1, 0);
3950 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3951 data = (const char *)req->buf + 3;
3954 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3955 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3958 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3959 reply_doserror(req, ERRDOS, ERRlock);
3960 END_PROFILE(SMBwriteunlock);
3965 /* The special X/Open SMB protocol handling of
3966 zero length writes is *NOT* done for
3968 if(numtowrite == 0) {
3971 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3974 status = sync_file(conn, fsp, False /* write through */);
3975 if (!NT_STATUS_IS_OK(status)) {
3976 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3977 fsp->fsp_name, nt_errstr(status) ));
3978 reply_nterror(req, status);
3982 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3983 reply_unixerror(req, ERRHRD, ERRdiskfull);
3988 status = do_unlock(smbd_messaging_context(),
3991 (uint64_t)numtowrite,
3995 if (NT_STATUS_V(status)) {
3996 reply_nterror(req, status);
4001 reply_outbuf(req, 1, 0);
4003 SSVAL(req->outbuf,smb_vwv0,nwritten);
4005 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4006 fsp->fnum, (int)numtowrite, (int)nwritten));
4010 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4013 END_PROFILE(SMBwriteunlock);
4018 #define DBGC_CLASS DBGC_ALL
4020 /****************************************************************************
4022 ****************************************************************************/
4024 void reply_write(struct smb_request *req)
4026 connection_struct *conn = req->conn;
4028 ssize_t nwritten = -1;
4032 struct lock_struct lock;
4035 START_PROFILE(SMBwrite);
4038 END_PROFILE(SMBwrite);
4039 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4043 /* If it's an IPC, pass off the pipe handler. */
4045 reply_pipe_write(req);
4046 END_PROFILE(SMBwrite);
4050 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4052 if (!check_fsp(conn, req, fsp)) {
4053 END_PROFILE(SMBwrite);
4057 if (!CHECK_WRITE(fsp)) {
4058 reply_doserror(req, ERRDOS, ERRbadaccess);
4059 END_PROFILE(SMBwrite);
4063 numtowrite = SVAL(req->vwv+1, 0);
4064 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4065 data = (const char *)req->buf + 3;
4067 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4068 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4071 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4072 reply_doserror(req, ERRDOS, ERRlock);
4073 END_PROFILE(SMBwrite);
4078 * X/Open SMB protocol says that if smb_vwv1 is
4079 * zero then the file size should be extended or
4080 * truncated to the size given in smb_vwv[2-3].
4083 if(numtowrite == 0) {
4085 * This is actually an allocate call, and set EOF. JRA.
4087 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4089 reply_nterror(req, NT_STATUS_DISK_FULL);
4092 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4094 reply_nterror(req, NT_STATUS_DISK_FULL);
4097 trigger_write_time_update_immediate(fsp);
4099 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4102 status = sync_file(conn, fsp, False);
4103 if (!NT_STATUS_IS_OK(status)) {
4104 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4105 fsp->fsp_name, nt_errstr(status) ));
4106 reply_nterror(req, status);
4110 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4111 reply_unixerror(req, ERRHRD, ERRdiskfull);
4115 reply_outbuf(req, 1, 0);
4117 SSVAL(req->outbuf,smb_vwv0,nwritten);
4119 if (nwritten < (ssize_t)numtowrite) {
4120 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4121 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4124 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4127 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4129 END_PROFILE(SMBwrite);
4133 /****************************************************************************
4134 Ensure a buffer is a valid writeX for recvfile purposes.
4135 ****************************************************************************/
4137 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4138 (2*14) + /* word count (including bcc) */ \
4141 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4144 connection_struct *conn = NULL;
4145 unsigned int doff = 0;
4146 size_t len = smb_len_large(inbuf);
4147 struct smbd_server_connection *sconn = smbd_server_conn;
4149 if (is_encrypted_packet(inbuf)) {
4150 /* Can't do this on encrypted
4155 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4159 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4160 CVAL(inbuf,smb_wct) != 14) {
4161 DEBUG(10,("is_valid_writeX_buffer: chained or "
4162 "invalid word length.\n"));
4166 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4168 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4172 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4175 if (IS_PRINT(conn)) {
4176 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4179 doff = SVAL(inbuf,smb_vwv11);
4181 numtowrite = SVAL(inbuf,smb_vwv10);
4183 if (len > doff && len - doff > 0xFFFF) {
4184 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4187 if (numtowrite == 0) {
4188 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4192 /* Ensure the sizes match up. */
4193 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4194 /* no pad byte...old smbclient :-( */
4195 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4197 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4201 if (len - doff != numtowrite) {
4202 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4203 "len = %u, doff = %u, numtowrite = %u\n",
4206 (unsigned int)numtowrite ));
4210 DEBUG(10,("is_valid_writeX_buffer: true "
4211 "len = %u, doff = %u, numtowrite = %u\n",
4214 (unsigned int)numtowrite ));
4219 /****************************************************************************
4220 Reply to a write and X.
4221 ****************************************************************************/
4223 void reply_write_and_X(struct smb_request *req)
4225 connection_struct *conn = req->conn;
4227 struct lock_struct lock;
4232 unsigned int smb_doff;
4233 unsigned int smblen;
4237 START_PROFILE(SMBwriteX);
4239 if ((req->wct != 12) && (req->wct != 14)) {
4240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4241 END_PROFILE(SMBwriteX);
4245 numtowrite = SVAL(req->vwv+10, 0);
4246 smb_doff = SVAL(req->vwv+11, 0);
4247 smblen = smb_len(req->inbuf);
4249 if (req->unread_bytes > 0xFFFF ||
4250 (smblen > smb_doff &&
4251 smblen - smb_doff > 0xFFFF)) {
4252 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4255 if (req->unread_bytes) {
4256 /* Can't do a recvfile write on IPC$ */
4258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4259 END_PROFILE(SMBwriteX);
4262 if (numtowrite != req->unread_bytes) {
4263 reply_doserror(req, ERRDOS, ERRbadmem);
4264 END_PROFILE(SMBwriteX);
4268 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4269 smb_doff + numtowrite > smblen) {
4270 reply_doserror(req, ERRDOS, ERRbadmem);
4271 END_PROFILE(SMBwriteX);
4276 /* If it's an IPC, pass off the pipe handler. */
4278 if (req->unread_bytes) {
4279 reply_doserror(req, ERRDOS, ERRbadmem);
4280 END_PROFILE(SMBwriteX);
4283 reply_pipe_write_and_X(req);
4284 END_PROFILE(SMBwriteX);
4288 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4289 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4290 write_through = BITSETW(req->vwv+7,0);
4292 if (!check_fsp(conn, req, fsp)) {
4293 END_PROFILE(SMBwriteX);
4297 if (!CHECK_WRITE(fsp)) {
4298 reply_doserror(req, ERRDOS, ERRbadaccess);
4299 END_PROFILE(SMBwriteX);
4303 data = smb_base(req->inbuf) + smb_doff;
4305 if(req->wct == 14) {
4306 #ifdef LARGE_SMB_OFF_T
4308 * This is a large offset (64 bit) write.
4310 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4312 #else /* !LARGE_SMB_OFF_T */
4315 * Ensure we haven't been sent a >32 bit offset.
4318 if(IVAL(req->vwv+12, 0) != 0) {
4319 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4320 "used and we don't support 64 bit offsets.\n",
4321 (unsigned int)IVAL(req->vwv+12, 0) ));
4322 reply_doserror(req, ERRDOS, ERRbadaccess);
4323 END_PROFILE(SMBwriteX);
4327 #endif /* LARGE_SMB_OFF_T */
4330 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4331 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4334 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4335 reply_doserror(req, ERRDOS, ERRlock);
4336 END_PROFILE(SMBwriteX);
4340 /* X/Open SMB protocol says that, unlike SMBwrite
4341 if the length is zero then NO truncation is
4342 done, just a write of zero. To truncate a file,
4345 if(numtowrite == 0) {
4349 if ((req->unread_bytes == 0) &&
4350 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4355 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4358 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4359 reply_unixerror(req, ERRHRD, ERRdiskfull);
4363 reply_outbuf(req, 6, 0);
4364 SSVAL(req->outbuf,smb_vwv2,nwritten);
4365 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4367 if (nwritten < (ssize_t)numtowrite) {
4368 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4369 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4372 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4373 fsp->fnum, (int)numtowrite, (int)nwritten));
4375 status = sync_file(conn, fsp, write_through);
4376 if (!NT_STATUS_IS_OK(status)) {
4377 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4378 fsp->fsp_name, nt_errstr(status) ));
4379 reply_nterror(req, status);
4383 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4385 END_PROFILE(SMBwriteX);
4390 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4392 END_PROFILE(SMBwriteX);
4396 /****************************************************************************
4398 ****************************************************************************/
4400 void reply_lseek(struct smb_request *req)
4402 connection_struct *conn = req->conn;
4408 START_PROFILE(SMBlseek);
4411 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4412 END_PROFILE(SMBlseek);
4416 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4418 if (!check_fsp(conn, req, fsp)) {
4422 flush_write_cache(fsp, SEEK_FLUSH);
4424 mode = SVAL(req->vwv+1, 0) & 3;
4425 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4426 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4435 res = fsp->fh->pos + startpos;
4446 if (umode == SEEK_END) {
4447 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4448 if(errno == EINVAL) {
4449 SMB_OFF_T current_pos = startpos;
4450 SMB_STRUCT_STAT sbuf;
4452 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4453 reply_unixerror(req, ERRDOS,
4455 END_PROFILE(SMBlseek);
4459 current_pos += sbuf.st_ex_size;
4461 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4466 reply_unixerror(req, ERRDOS, ERRnoaccess);
4467 END_PROFILE(SMBlseek);
4474 reply_outbuf(req, 2, 0);
4475 SIVAL(req->outbuf,smb_vwv0,res);
4477 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4478 fsp->fnum, (double)startpos, (double)res, mode));
4480 END_PROFILE(SMBlseek);
4484 /****************************************************************************
4486 ****************************************************************************/
4488 void reply_flush(struct smb_request *req)
4490 connection_struct *conn = req->conn;
4494 START_PROFILE(SMBflush);
4497 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4501 fnum = SVAL(req->vwv+0, 0);
4502 fsp = file_fsp(req, fnum);
4504 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4509 file_sync_all(conn);
4511 NTSTATUS status = sync_file(conn, fsp, True);
4512 if (!NT_STATUS_IS_OK(status)) {
4513 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4514 fsp->fsp_name, nt_errstr(status) ));
4515 reply_nterror(req, status);
4516 END_PROFILE(SMBflush);
4521 reply_outbuf(req, 0, 0);
4523 DEBUG(3,("flush\n"));
4524 END_PROFILE(SMBflush);
4528 /****************************************************************************
4530 conn POINTER CAN BE NULL HERE !
4531 ****************************************************************************/
4533 void reply_exit(struct smb_request *req)
4535 START_PROFILE(SMBexit);
4537 file_close_pid(req->smbpid, req->vuid);
4539 reply_outbuf(req, 0, 0);
4541 DEBUG(3,("exit\n"));
4543 END_PROFILE(SMBexit);
4547 /****************************************************************************
4548 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4549 ****************************************************************************/
4551 void reply_close(struct smb_request *req)
4553 connection_struct *conn = req->conn;
4554 NTSTATUS status = NT_STATUS_OK;
4555 files_struct *fsp = NULL;
4556 START_PROFILE(SMBclose);
4559 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4560 END_PROFILE(SMBclose);
4564 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4567 * We can only use check_fsp if we know it's not a directory.
4570 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4571 reply_doserror(req, ERRDOS, ERRbadfid);
4572 END_PROFILE(SMBclose);
4576 if(fsp->is_directory) {
4578 * Special case - close NT SMB directory handle.
4580 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4581 status = close_file(req, fsp, NORMAL_CLOSE);
4585 * Close ordinary file.
4588 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4589 fsp->fh->fd, fsp->fnum,
4590 conn->num_files_open));
4593 * Take care of any time sent in the close.
4596 t = srv_make_unix_date3(req->vwv+1);
4597 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4600 * close_file() returns the unix errno if an error
4601 * was detected on close - normally this is due to
4602 * a disk full error. If not then it was probably an I/O error.
4605 status = close_file(req, fsp, NORMAL_CLOSE);
4608 if (!NT_STATUS_IS_OK(status)) {
4609 reply_nterror(req, status);
4610 END_PROFILE(SMBclose);
4614 reply_outbuf(req, 0, 0);
4615 END_PROFILE(SMBclose);
4619 /****************************************************************************
4620 Reply to a writeclose (Core+ protocol).
4621 ****************************************************************************/
4623 void reply_writeclose(struct smb_request *req)
4625 connection_struct *conn = req->conn;
4627 ssize_t nwritten = -1;
4628 NTSTATUS close_status = NT_STATUS_OK;
4631 struct timespec mtime;
4633 struct lock_struct lock;
4635 START_PROFILE(SMBwriteclose);
4638 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4639 END_PROFILE(SMBwriteclose);
4643 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4645 if (!check_fsp(conn, req, fsp)) {
4646 END_PROFILE(SMBwriteclose);
4649 if (!CHECK_WRITE(fsp)) {
4650 reply_doserror(req, ERRDOS,ERRbadaccess);
4651 END_PROFILE(SMBwriteclose);
4655 numtowrite = SVAL(req->vwv+1, 0);
4656 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4657 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4658 data = (const char *)req->buf + 1;
4661 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4662 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4665 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4666 reply_doserror(req, ERRDOS,ERRlock);
4667 END_PROFILE(SMBwriteclose);
4672 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4674 set_close_write_time(fsp, mtime);
4677 * More insanity. W2K only closes the file if writelen > 0.
4682 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4684 close_status = close_file(req, fsp, NORMAL_CLOSE);
4687 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4688 fsp->fnum, (int)numtowrite, (int)nwritten,
4689 conn->num_files_open));
4691 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4692 reply_doserror(req, ERRHRD, ERRdiskfull);
4696 if(!NT_STATUS_IS_OK(close_status)) {
4697 reply_nterror(req, close_status);
4701 reply_outbuf(req, 1, 0);
4703 SSVAL(req->outbuf,smb_vwv0,nwritten);
4707 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4710 END_PROFILE(SMBwriteclose);
4715 #define DBGC_CLASS DBGC_LOCKING
4717 /****************************************************************************
4719 ****************************************************************************/
4721 void reply_lock(struct smb_request *req)
4723 connection_struct *conn = req->conn;
4724 uint64_t count,offset;
4727 struct byte_range_lock *br_lck = NULL;
4729 START_PROFILE(SMBlock);
4732 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4733 END_PROFILE(SMBlock);
4737 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4739 if (!check_fsp(conn, req, fsp)) {
4740 END_PROFILE(SMBlock);
4744 count = (uint64_t)IVAL(req->vwv+1, 0);
4745 offset = (uint64_t)IVAL(req->vwv+3, 0);
4747 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4748 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4750 br_lck = do_lock(smbd_messaging_context(),
4757 False, /* Non-blocking lock. */
4762 TALLOC_FREE(br_lck);
4764 if (NT_STATUS_V(status)) {
4765 reply_nterror(req, status);
4766 END_PROFILE(SMBlock);
4770 reply_outbuf(req, 0, 0);
4772 END_PROFILE(SMBlock);
4776 /****************************************************************************
4778 ****************************************************************************/
4780 void reply_unlock(struct smb_request *req)
4782 connection_struct *conn = req->conn;
4783 uint64_t count,offset;
4787 START_PROFILE(SMBunlock);
4790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4791 END_PROFILE(SMBunlock);
4795 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4797 if (!check_fsp(conn, req, fsp)) {
4798 END_PROFILE(SMBunlock);
4802 count = (uint64_t)IVAL(req->vwv+1, 0);
4803 offset = (uint64_t)IVAL(req->vwv+3, 0);
4805 status = do_unlock(smbd_messaging_context(),
4812 if (NT_STATUS_V(status)) {
4813 reply_nterror(req, status);
4814 END_PROFILE(SMBunlock);
4818 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4819 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4821 reply_outbuf(req, 0, 0);
4823 END_PROFILE(SMBunlock);
4828 #define DBGC_CLASS DBGC_ALL
4830 /****************************************************************************
4832 conn POINTER CAN BE NULL HERE !
4833 ****************************************************************************/
4835 void reply_tdis(struct smb_request *req)
4837 struct smbd_server_connection *sconn = smbd_server_conn;
4838 connection_struct *conn = req->conn;
4839 START_PROFILE(SMBtdis);
4842 DEBUG(4,("Invalid connection in tdis\n"));
4843 reply_doserror(req, ERRSRV, ERRinvnid);
4844 END_PROFILE(SMBtdis);
4850 close_cnum(sconn, conn,req->vuid);
4853 reply_outbuf(req, 0, 0);
4854 END_PROFILE(SMBtdis);
4858 /****************************************************************************
4860 conn POINTER CAN BE NULL HERE !
4861 ****************************************************************************/
4863 void reply_echo(struct smb_request *req)
4865 connection_struct *conn = req->conn;
4866 struct smb_perfcount_data local_pcd;
4867 struct smb_perfcount_data *cur_pcd;
4871 START_PROFILE(SMBecho);
4873 smb_init_perfcount_data(&local_pcd);
4876 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4877 END_PROFILE(SMBecho);
4881 smb_reverb = SVAL(req->vwv+0, 0);
4883 reply_outbuf(req, 1, req->buflen);
4885 /* copy any incoming data back out */
4886 if (req->buflen > 0) {
4887 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4890 if (smb_reverb > 100) {
4891 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4895 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4897 /* this makes sure we catch the request pcd */
4898 if (seq_num == smb_reverb) {
4899 cur_pcd = &req->pcd;
4901 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4902 cur_pcd = &local_pcd;
4905 SSVAL(req->outbuf,smb_vwv0,seq_num);
4907 show_msg((char *)req->outbuf);
4908 if (!srv_send_smb(smbd_server_fd(),
4909 (char *)req->outbuf,
4910 true, req->seqnum+1,
4911 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4913 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4916 DEBUG(3,("echo %d times\n", smb_reverb));
4918 TALLOC_FREE(req->outbuf);
4920 END_PROFILE(SMBecho);
4924 /****************************************************************************
4925 Reply to a printopen.
4926 ****************************************************************************/
4928 void reply_printopen(struct smb_request *req)
4930 connection_struct *conn = req->conn;
4932 SMB_STRUCT_STAT sbuf;
4935 START_PROFILE(SMBsplopen);
4938 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4939 END_PROFILE(SMBsplopen);
4943 if (!CAN_PRINT(conn)) {
4944 reply_doserror(req, ERRDOS, ERRnoaccess);
4945 END_PROFILE(SMBsplopen);
4949 status = file_new(req, conn, &fsp);
4950 if(!NT_STATUS_IS_OK(status)) {
4951 reply_nterror(req, status);
4952 END_PROFILE(SMBsplopen);
4956 /* Open for exclusive use, write only. */
4957 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4959 if (!NT_STATUS_IS_OK(status)) {
4960 file_free(req, fsp);
4961 reply_nterror(req, status);
4962 END_PROFILE(SMBsplopen);
4966 reply_outbuf(req, 1, 0);
4967 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4969 DEBUG(3,("openprint fd=%d fnum=%d\n",
4970 fsp->fh->fd, fsp->fnum));
4972 END_PROFILE(SMBsplopen);
4976 /****************************************************************************
4977 Reply to a printclose.
4978 ****************************************************************************/
4980 void reply_printclose(struct smb_request *req)
4982 connection_struct *conn = req->conn;
4986 START_PROFILE(SMBsplclose);
4989 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4990 END_PROFILE(SMBsplclose);
4994 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4996 if (!check_fsp(conn, req, fsp)) {
4997 END_PROFILE(SMBsplclose);
5001 if (!CAN_PRINT(conn)) {
5002 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
5003 END_PROFILE(SMBsplclose);
5007 DEBUG(3,("printclose fd=%d fnum=%d\n",
5008 fsp->fh->fd,fsp->fnum));
5010 status = close_file(req, fsp, NORMAL_CLOSE);
5012 if(!NT_STATUS_IS_OK(status)) {
5013 reply_nterror(req, status);
5014 END_PROFILE(SMBsplclose);
5018 reply_outbuf(req, 0, 0);
5020 END_PROFILE(SMBsplclose);
5024 /****************************************************************************
5025 Reply to a printqueue.
5026 ****************************************************************************/
5028 void reply_printqueue(struct smb_request *req)
5030 connection_struct *conn = req->conn;
5034 START_PROFILE(SMBsplretq);
5037 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5038 END_PROFILE(SMBsplretq);
5042 max_count = SVAL(req->vwv+0, 0);
5043 start_index = SVAL(req->vwv+1, 0);
5045 /* we used to allow the client to get the cnum wrong, but that
5046 is really quite gross and only worked when there was only
5047 one printer - I think we should now only accept it if they
5048 get it right (tridge) */
5049 if (!CAN_PRINT(conn)) {
5050 reply_doserror(req, ERRDOS, ERRnoaccess);
5051 END_PROFILE(SMBsplretq);
5055 reply_outbuf(req, 2, 3);
5056 SSVAL(req->outbuf,smb_vwv0,0);
5057 SSVAL(req->outbuf,smb_vwv1,0);
5058 SCVAL(smb_buf(req->outbuf),0,1);
5059 SSVAL(smb_buf(req->outbuf),1,0);
5061 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5062 start_index, max_count));
5065 print_queue_struct *queue = NULL;
5066 print_status_struct status;
5067 int count = print_queue_status(SNUM(conn), &queue, &status);
5068 int num_to_get = ABS(max_count);
5069 int first = (max_count>0?start_index:start_index+max_count+1);
5075 num_to_get = MIN(num_to_get,count-first);
5078 for (i=first;i<first+num_to_get;i++) {
5082 srv_put_dos_date2(p,0,queue[i].time);
5083 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5084 SSVAL(p,5, queue[i].job);
5085 SIVAL(p,7,queue[i].size);
5087 srvstr_push(blob, req->flags2, p+12,
5088 queue[i].fs_user, 16, STR_ASCII);
5090 if (message_push_blob(
5093 blob, sizeof(blob))) == -1) {
5094 reply_nterror(req, NT_STATUS_NO_MEMORY);
5095 END_PROFILE(SMBsplretq);
5101 SSVAL(req->outbuf,smb_vwv0,count);
5102 SSVAL(req->outbuf,smb_vwv1,
5103 (max_count>0?first+count:first-1));
5104 SCVAL(smb_buf(req->outbuf),0,1);
5105 SSVAL(smb_buf(req->outbuf),1,28*count);
5110 DEBUG(3,("%d entries returned in queue\n",count));
5113 END_PROFILE(SMBsplretq);
5117 /****************************************************************************
5118 Reply to a printwrite.
5119 ****************************************************************************/
5121 void reply_printwrite(struct smb_request *req)
5123 connection_struct *conn = req->conn;
5128 START_PROFILE(SMBsplwr);
5131 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5132 END_PROFILE(SMBsplwr);
5136 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5138 if (!check_fsp(conn, req, fsp)) {
5139 END_PROFILE(SMBsplwr);
5143 if (!CAN_PRINT(conn)) {
5144 reply_doserror(req, ERRDOS, ERRnoaccess);
5145 END_PROFILE(SMBsplwr);
5149 if (!CHECK_WRITE(fsp)) {
5150 reply_doserror(req, ERRDOS, ERRbadaccess);
5151 END_PROFILE(SMBsplwr);
5155 numtowrite = SVAL(req->buf, 1);
5157 if (req->buflen < numtowrite + 3) {
5158 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5159 END_PROFILE(SMBsplwr);
5163 data = (const char *)req->buf + 3;
5165 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5166 reply_unixerror(req, ERRHRD, ERRdiskfull);
5167 END_PROFILE(SMBsplwr);
5171 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5173 END_PROFILE(SMBsplwr);
5177 /****************************************************************************
5179 ****************************************************************************/
5181 void reply_mkdir(struct smb_request *req)
5183 connection_struct *conn = req->conn;
5184 struct smb_filename *smb_dname = NULL;
5185 char *directory = NULL;
5187 TALLOC_CTX *ctx = talloc_tos();
5189 START_PROFILE(SMBmkdir);
5191 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5192 STR_TERMINATE, &status);
5193 if (!NT_STATUS_IS_OK(status)) {
5194 reply_nterror(req, status);
5198 status = filename_convert(ctx, conn,
5199 req->flags2 & FLAGS2_DFS_PATHNAMES,
5203 if (!NT_STATUS_IS_OK(status)) {
5204 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5205 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5206 ERRSRV, ERRbadpath);
5209 reply_nterror(req, status);
5213 status = create_directory(conn, req, smb_dname);
5215 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5217 if (!NT_STATUS_IS_OK(status)) {
5219 if (!use_nt_status()
5220 && NT_STATUS_EQUAL(status,
5221 NT_STATUS_OBJECT_NAME_COLLISION)) {
5223 * Yes, in the DOS error code case we get a
5224 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5225 * samba4 torture test.
5227 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5230 reply_nterror(req, status);
5234 reply_outbuf(req, 0, 0);
5236 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5238 TALLOC_FREE(smb_dname);
5239 END_PROFILE(SMBmkdir);
5243 /****************************************************************************
5244 Static function used by reply_rmdir to delete an entire directory
5245 tree recursively. Return True on ok, False on fail.
5246 ****************************************************************************/
5248 static bool recursive_rmdir(TALLOC_CTX *ctx,
5249 connection_struct *conn,
5250 struct smb_filename *smb_dname)
5252 const char *dname = NULL;
5256 struct smb_Dir *dir_hnd;
5258 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5260 dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0);
5264 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5265 struct smb_filename *smb_dname_full = NULL;
5266 char *fullname = NULL;
5267 bool do_break = true;
5270 if (ISDOT(dname) || ISDOTDOT(dname)) {
5274 if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
5279 /* Construct the full name. */
5280 fullname = talloc_asprintf(ctx,
5282 smb_dname->base_name,
5289 status = create_synthetic_smb_fname(talloc_tos(), fullname,
5292 if (!NT_STATUS_IS_OK(status)) {
5296 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5300 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5301 if(!recursive_rmdir(ctx, conn, smb_dname_full)) {
5304 if(SMB_VFS_RMDIR(conn,
5305 smb_dname_full->base_name) != 0) {
5308 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5312 /* Successful iteration. */
5316 TALLOC_FREE(smb_dname_full);
5317 TALLOC_FREE(fullname);
5323 TALLOC_FREE(dir_hnd);
5327 /****************************************************************************
5328 The internals of the rmdir code - called elsewhere.
5329 ****************************************************************************/
5331 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5332 connection_struct *conn,
5333 struct smb_filename *smb_dname)
5338 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5340 /* Might be a symlink. */
5341 if(SMB_VFS_LSTAT(conn, smb_dname) != 0) {
5342 return map_nt_error_from_unix(errno);
5345 if (S_ISLNK(smb_dname->st.st_ex_mode)) {
5346 /* Is what it points to a directory ? */
5347 if(SMB_VFS_STAT(conn, smb_dname) != 0) {
5348 return map_nt_error_from_unix(errno);
5350 if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
5351 return NT_STATUS_NOT_A_DIRECTORY;
5353 ret = SMB_VFS_UNLINK(conn, smb_dname);
5355 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5358 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5359 FILE_NOTIFY_CHANGE_DIR_NAME,
5360 smb_dname->base_name);
5361 return NT_STATUS_OK;
5364 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5366 * Check to see if the only thing in this directory are
5367 * vetoed files/directories. If so then delete them and
5368 * retry. If we fail to delete any of them (and we *don't*
5369 * do a recursive delete) then fail the rmdir.
5373 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5374 smb_dname->base_name, NULL,
5377 if(dir_hnd == NULL) {
5382 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5383 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5385 if (!is_visible_file(conn, smb_dname->base_name, dname,
5388 if(!IS_VETO_PATH(conn, dname)) {
5389 TALLOC_FREE(dir_hnd);
5395 /* We only have veto files/directories.
5396 * Are we allowed to delete them ? */
5398 if(!lp_recursive_veto_delete(SNUM(conn))) {
5399 TALLOC_FREE(dir_hnd);
5404 /* Do a recursive delete. */
5405 RewindDir(dir_hnd,&dirpos);
5406 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5407 struct smb_filename *smb_dname_full = NULL;
5408 char *fullname = NULL;
5409 bool do_break = true;
5412 if (ISDOT(dname) || ISDOTDOT(dname)) {
5415 if (!is_visible_file(conn, smb_dname->base_name, dname,
5420 fullname = talloc_asprintf(ctx,
5422 smb_dname->base_name,
5430 status = create_synthetic_smb_fname(talloc_tos(),
5434 if (!NT_STATUS_IS_OK(status)) {
5435 errno = map_errno_from_nt_status(status);
5439 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5442 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5443 if(!recursive_rmdir(ctx, conn,
5447 if(SMB_VFS_RMDIR(conn,
5448 smb_dname_full->base_name) != 0) {
5451 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5455 /* Successful iteration. */
5459 TALLOC_FREE(fullname);
5460 TALLOC_FREE(smb_dname_full);
5464 TALLOC_FREE(dir_hnd);
5465 /* Retry the rmdir */
5466 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5472 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5473 "%s\n", smb_fname_str_dbg(smb_dname),
5475 return map_nt_error_from_unix(errno);
5478 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5479 FILE_NOTIFY_CHANGE_DIR_NAME,
5480 smb_dname->base_name);
5482 return NT_STATUS_OK;
5485 /****************************************************************************
5487 ****************************************************************************/
5489 void reply_rmdir(struct smb_request *req)
5491 connection_struct *conn = req->conn;
5492 struct smb_filename *smb_dname = NULL;
5493 char *directory = NULL;
5495 TALLOC_CTX *ctx = talloc_tos();
5497 START_PROFILE(SMBrmdir);
5499 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5500 STR_TERMINATE, &status);
5501 if (!NT_STATUS_IS_OK(status)) {
5502 reply_nterror(req, status);
5506 status = filename_convert(ctx, conn,
5507 req->flags2 & FLAGS2_DFS_PATHNAMES,
5511 if (!NT_STATUS_IS_OK(status)) {
5512 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5513 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5514 ERRSRV, ERRbadpath);
5517 reply_nterror(req, status);
5521 dptr_closepath(directory, req->smbpid);
5522 status = rmdir_internals(ctx, conn, smb_dname);
5523 if (!NT_STATUS_IS_OK(status)) {
5524 reply_nterror(req, status);
5528 reply_outbuf(req, 0, 0);
5530 DEBUG( 3, ( "rmdir %s\n", directory ) );
5532 TALLOC_FREE(smb_dname);
5533 END_PROFILE(SMBrmdir);
5537 /*******************************************************************
5538 Resolve wildcards in a filename rename.
5539 ********************************************************************/
5541 static bool resolve_wildcards(TALLOC_CTX *ctx,
5546 char *name2_copy = NULL;
5551 char *p,*p2, *pname1, *pname2;
5553 name2_copy = talloc_strdup(ctx, name2);
5558 pname1 = strrchr_m(name1,'/');
5559 pname2 = strrchr_m(name2_copy,'/');
5561 if (!pname1 || !pname2) {
5565 /* Truncate the copy of name2 at the last '/' */
5568 /* Now go past the '/' */
5572 root1 = talloc_strdup(ctx, pname1);
5573 root2 = talloc_strdup(ctx, pname2);
5575 if (!root1 || !root2) {
5579 p = strrchr_m(root1,'.');
5582 ext1 = talloc_strdup(ctx, p+1);
5584 ext1 = talloc_strdup(ctx, "");
5586 p = strrchr_m(root2,'.');
5589 ext2 = talloc_strdup(ctx, p+1);
5591 ext2 = talloc_strdup(ctx, "");
5594 if (!ext1 || !ext2) {
5602 /* Hmmm. Should this be mb-aware ? */
5605 } else if (*p2 == '*') {
5607 root2 = talloc_asprintf(ctx, "%s%s",
5626 /* Hmmm. Should this be mb-aware ? */
5629 } else if (*p2 == '*') {
5631 ext2 = talloc_asprintf(ctx, "%s%s",
5647 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5652 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5664 /****************************************************************************
5665 Ensure open files have their names updated. Updated to notify other smbd's
5667 ****************************************************************************/
5669 static void rename_open_files(connection_struct *conn,
5670 struct share_mode_lock *lck,
5671 const struct smb_filename *smb_fname_dst)
5674 bool did_rename = False;
5675 char *fname_dst = NULL;
5678 status = get_full_smb_filename(talloc_tos(), smb_fname_dst,
5680 if (!NT_STATUS_IS_OK(status)) {
5684 for(fsp = file_find_di_first(lck->id); fsp;
5685 fsp = file_find_di_next(fsp)) {
5686 /* fsp_name is a relative path under the fsp. To change this for other
5687 sharepaths we need to manipulate relative paths. */
5688 /* TODO - create the absolute path and manipulate the newname
5689 relative to the sharepath. */
5690 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5693 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5694 "(file_id %s) from %s -> %s\n", fsp->fnum,
5695 file_id_string_tos(&fsp->file_id), fsp->fsp_name,
5696 smb_fname_str_dbg(smb_fname_dst)));
5697 string_set(&fsp->fsp_name, fname_dst);
5702 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5703 "for %s\n", file_id_string_tos(&lck->id),
5704 smb_fname_str_dbg(smb_fname_dst)));
5707 /* Send messages to all smbd's (not ourself) that the name has changed. */
5708 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5710 TALLOC_FREE(fname_dst);
5713 /****************************************************************************
5714 We need to check if the source path is a parent directory of the destination
5715 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5716 refuse the rename with a sharing violation. Under UNIX the above call can
5717 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5718 probably need to check that the client is a Windows one before disallowing
5719 this as a UNIX client (one with UNIX extensions) can know the source is a
5720 symlink and make this decision intelligently. Found by an excellent bug
5721 report from <AndyLiebman@aol.com>.
5722 ****************************************************************************/
5724 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5725 const struct smb_filename *smb_fname_dst)
5727 const char *psrc = smb_fname_src->base_name;
5728 const char *pdst = smb_fname_dst->base_name;
5731 if (psrc[0] == '.' && psrc[1] == '/') {
5734 if (pdst[0] == '.' && pdst[1] == '/') {
5737 if ((slen = strlen(psrc)) > strlen(pdst)) {
5740 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5744 * Do the notify calls from a rename
5747 static void notify_rename(connection_struct *conn, bool is_dir,
5748 const struct smb_filename *smb_fname_src,
5749 const struct smb_filename *smb_fname_dst)
5751 char *parent_dir_src = NULL;
5752 char *parent_dir_dst = NULL;
5753 char *fname_src = NULL;
5754 char *fname_dst = NULL;
5758 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5759 : FILE_NOTIFY_CHANGE_FILE_NAME;
5761 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5762 &parent_dir_src, NULL) ||
5763 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5764 &parent_dir_dst, NULL)) {
5768 status = get_full_smb_filename(talloc_tos(), smb_fname_src,
5770 if (!NT_STATUS_IS_OK(status)) {
5773 status = get_full_smb_filename(talloc_tos(), smb_fname_dst,
5775 if (!NT_STATUS_IS_OK(status)) {
5779 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5780 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, fname_src);
5781 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, fname_dst);
5784 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, fname_src);
5785 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, fname_dst);
5788 /* this is a strange one. w2k3 gives an additional event for
5789 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5790 files, but not directories */
5792 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5793 FILE_NOTIFY_CHANGE_ATTRIBUTES
5794 |FILE_NOTIFY_CHANGE_CREATION,
5798 TALLOC_FREE(parent_dir_src);
5799 TALLOC_FREE(parent_dir_dst);
5800 TALLOC_FREE(fname_src);
5801 TALLOC_FREE(fname_dst);
5804 /****************************************************************************
5805 Rename an open file - given an fsp.
5806 ****************************************************************************/
5808 NTSTATUS rename_internals_fsp(connection_struct *conn,
5810 const struct smb_filename *smb_fname_dst_in,
5812 bool replace_if_exists)
5814 TALLOC_CTX *ctx = talloc_tos();
5815 struct smb_filename *smb_fname_src = NULL;
5816 struct smb_filename *smb_fname_dst = NULL;
5817 SMB_STRUCT_STAT sbuf;
5818 NTSTATUS status = NT_STATUS_OK;
5819 struct share_mode_lock *lck = NULL;
5820 bool dst_exists, old_is_stream, new_is_stream;
5824 status = check_name(conn, smb_fname_dst_in->base_name);
5825 if (!NT_STATUS_IS_OK(status)) {
5829 /* Make a copy of the src and dst smb_fname structs */
5830 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5831 if (!NT_STATUS_IS_OK(status)) {
5836 * This will be replaced with copy_smb_filename() when fsp->fsp_name
5837 * is converted to store an smb_filename struct.
5839 status = create_synthetic_smb_fname_split(ctx, fsp->fsp_name, NULL,
5841 if (!NT_STATUS_IS_OK(status)) {
5845 /* Ensure the dst smb_fname contains a '/' */
5846 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5848 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5849 smb_fname_dst->base_name);
5851 status = NT_STATUS_NO_MEMORY;
5854 TALLOC_FREE(smb_fname_dst->base_name);
5855 smb_fname_dst->base_name = tmp;
5859 * Check for special case with case preserving and not
5860 * case sensitive. If the old last component differs from the original
5861 * last component only by case, then we should allow
5862 * the rename (user is trying to change the case of the
5865 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5866 strequal(smb_fname_src->base_name, smb_fname_dst->base_name) &&
5867 strequal(smb_fname_src->stream_name, smb_fname_dst->stream_name)) {
5869 char *fname_dst_lcomp_base_mod = NULL;
5870 struct smb_filename *smb_fname_orig_lcomp = NULL;
5873 * Get the last component of the destination name. Note that
5874 * we guarantee that destination name contains a '/' character
5877 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5878 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5879 if (!fname_dst_lcomp_base_mod) {
5880 status = NT_STATUS_NO_MEMORY;
5885 * Create an smb_filename struct using the original last
5886 * component of the destination.
5888 status = create_synthetic_smb_fname_split(ctx,
5889 smb_fname_dst->original_lcomp, NULL,
5890 &smb_fname_orig_lcomp);
5891 if (!NT_STATUS_IS_OK(status)) {
5892 TALLOC_FREE(fname_dst_lcomp_base_mod);
5896 /* If the base names only differ by case, use original. */
5897 if(!strcsequal(fname_dst_lcomp_base_mod,
5898 smb_fname_orig_lcomp->base_name)) {
5901 * Replace the modified last component with the
5904 *last_slash = '\0'; /* Truncate at the '/' */
5905 tmp = talloc_asprintf(smb_fname_dst,
5907 smb_fname_dst->base_name,
5908 smb_fname_orig_lcomp->base_name);
5910 status = NT_STATUS_NO_MEMORY;
5911 TALLOC_FREE(fname_dst_lcomp_base_mod);
5912 TALLOC_FREE(smb_fname_orig_lcomp);
5915 TALLOC_FREE(smb_fname_dst->base_name);
5916 smb_fname_dst->base_name = tmp;
5919 /* If the stream_names only differ by case, use original. */
5920 if(!strcsequal(smb_fname_dst->stream_name,
5921 smb_fname_orig_lcomp->stream_name)) {
5923 /* Use the original stream. */
5924 tmp = talloc_strdup(smb_fname_dst,
5925 smb_fname_orig_lcomp->stream_name);
5927 status = NT_STATUS_NO_MEMORY;
5928 TALLOC_FREE(fname_dst_lcomp_base_mod);
5929 TALLOC_FREE(smb_fname_orig_lcomp);
5932 TALLOC_FREE(smb_fname_dst->stream_name);
5933 smb_fname_dst->stream_name = tmp;
5935 TALLOC_FREE(fname_dst_lcomp_base_mod);
5936 TALLOC_FREE(smb_fname_orig_lcomp);
5940 * If the src and dest names are identical - including case,
5941 * don't do the rename, just return success.
5944 if (strcsequal(smb_fname_src->base_name, smb_fname_dst->base_name) &&
5945 strcsequal(smb_fname_src->stream_name,
5946 smb_fname_dst->stream_name)) {
5947 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5948 "- returning success\n",
5949 smb_fname_str_dbg(smb_fname_dst)));
5950 status = NT_STATUS_OK;
5954 old_is_stream = is_ntfs_stream_smb_fname(smb_fname_src);
5955 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5957 /* Return the correct error code if both names aren't streams. */
5958 if (!old_is_stream && new_is_stream) {
5959 status = NT_STATUS_OBJECT_NAME_INVALID;
5963 if (old_is_stream && !new_is_stream) {
5964 status = NT_STATUS_INVALID_PARAMETER;
5968 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
5970 if(!replace_if_exists && dst_exists) {
5971 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
5972 "%s -> %s\n", smb_fname_str_dbg(smb_fname_src),
5973 smb_fname_str_dbg(smb_fname_dst)));
5974 status = NT_STATUS_OBJECT_NAME_COLLISION;
5979 struct file_id fileid = vfs_file_id_from_sbuf(conn,
5980 &smb_fname_dst->st);
5981 files_struct *dst_fsp = file_find_di_first(fileid);
5982 /* The file can be open when renaming a stream */
5983 if (dst_fsp && !new_is_stream) {
5984 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5985 status = NT_STATUS_ACCESS_DENIED;
5990 /* Ensure we have a valid stat struct for the source. */
5991 if (fsp->fh->fd != -1) {
5992 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5993 status = map_nt_error_from_unix(errno);
5998 if (fsp->posix_open) {
5999 ret = SMB_VFS_LSTAT(conn, smb_fname_src);
6002 ret = SMB_VFS_STAT(conn, smb_fname_src);
6005 status = map_nt_error_from_unix(errno);
6008 sbuf = smb_fname_src->st;
6011 status = can_rename(conn, fsp, attrs, &sbuf);
6013 if (!NT_STATUS_IS_OK(status)) {
6014 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6015 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6016 smb_fname_str_dbg(smb_fname_dst)));
6017 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6018 status = NT_STATUS_ACCESS_DENIED;
6022 if (rename_path_prefix_equal(smb_fname_src, smb_fname_dst)) {
6023 status = NT_STATUS_ACCESS_DENIED;
6026 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6030 * We have the file open ourselves, so not being able to get the
6031 * corresponding share mode lock is a fatal error.
6034 SMB_ASSERT(lck != NULL);
6036 if(SMB_VFS_RENAME(conn, smb_fname_src, smb_fname_dst) == 0) {
6037 uint32 create_options = fsp->fh->private_options;
6039 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6040 "%s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6041 smb_fname_str_dbg(smb_fname_dst)));
6043 notify_rename(conn, fsp->is_directory, smb_fname_src,
6046 rename_open_files(conn, lck, smb_fname_dst);
6049 * A rename acts as a new file create w.r.t. allowing an initial delete
6050 * on close, probably because in Windows there is a new handle to the
6051 * new file. If initial delete on close was requested but not
6052 * originally set, we need to set it here. This is probably not 100% correct,
6053 * but will work for the CIFSFS client which in non-posix mode
6054 * depends on these semantics. JRA.
6057 if (create_options & FILE_DELETE_ON_CLOSE) {
6058 status = can_set_delete_on_close(fsp, True, 0);
6060 if (NT_STATUS_IS_OK(status)) {
6061 /* Note that here we set the *inital* delete on close flag,
6062 * not the regular one. The magic gets handled in close. */
6063 fsp->initial_delete_on_close = True;
6067 status = NT_STATUS_OK;
6073 if (errno == ENOTDIR || errno == EISDIR) {
6074 status = NT_STATUS_OBJECT_NAME_COLLISION;
6076 status = map_nt_error_from_unix(errno);
6079 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6080 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6081 smb_fname_str_dbg(smb_fname_dst)));
6084 TALLOC_FREE(smb_fname_src);
6085 TALLOC_FREE(smb_fname_dst);
6090 /****************************************************************************
6091 The guts of the rename command, split out so it may be called by the NT SMB
6093 ****************************************************************************/
6095 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6096 connection_struct *conn,
6097 struct smb_request *req,
6098 const char *name_in,
6099 const char *newname_in,
6101 bool replace_if_exists,
6104 uint32_t access_mask)
6106 struct smb_filename *smb_fname_src = NULL;
6107 struct smb_filename *smb_fname_dst = NULL;
6108 char *fname_src_dir = NULL;
6109 char *fname_src_mask = NULL;
6111 NTSTATUS status = NT_STATUS_OK;
6112 struct smb_Dir *dir_hnd = NULL;
6115 int create_options = 0;
6116 bool posix_pathnames = lp_posix_pathnames();
6118 status = unix_convert(ctx, conn, name_in, &smb_fname_src,
6119 src_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6120 if (!NT_STATUS_IS_OK(status)) {
6124 status = unix_convert(ctx, conn, newname_in, &smb_fname_dst,
6126 (dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0)));
6127 if (!NT_STATUS_IS_OK(status)) {
6132 * Split the old name into directory and last component
6133 * strings. Note that unix_convert may have stripped off a
6134 * leading ./ from both name and newname if the rename is
6135 * at the root of the share. We need to make sure either both
6136 * name and newname contain a / character or neither of them do
6137 * as this is checked in resolve_wildcards().
6140 /* Split up the directory from the filename/mask. */
6141 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6142 &fname_src_dir, &fname_src_mask);
6143 if (!NT_STATUS_IS_OK(status)) {
6144 status = NT_STATUS_NO_MEMORY;
6149 * We should only check the mangled cache
6150 * here if unix_convert failed. This means
6151 * that the path in 'mask' doesn't exist
6152 * on the file system and so we need to look
6153 * for a possible mangle. This patch from
6154 * Tine Smukavec <valentin.smukavec@hermes.si>.
6157 if (!VALID_STAT(smb_fname_src->st) &&
6158 mangle_is_mangled(fname_src_mask, conn->params)) {
6159 char *new_mask = NULL;
6160 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6163 TALLOC_FREE(fname_src_mask);
6164 fname_src_mask = new_mask;
6168 if (!src_has_wild) {
6172 * Only one file needs to be renamed. Append the mask back
6173 * onto the directory.
6175 TALLOC_FREE(smb_fname_src->base_name);
6176 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6180 if (!smb_fname_src->base_name) {
6181 status = NT_STATUS_NO_MEMORY;
6185 /* Ensure dst fname contains a '/' also */
6186 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6188 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6189 smb_fname_dst->base_name);
6191 status = NT_STATUS_NO_MEMORY;
6194 TALLOC_FREE(smb_fname_dst->base_name);
6195 smb_fname_dst->base_name = tmp;
6198 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6199 "case_preserve = %d, short case preserve = %d, "
6200 "directory = %s, newname = %s, "
6201 "last_component_dest = %s\n",
6202 conn->case_sensitive, conn->case_preserve,
6203 conn->short_case_preserve,
6204 smb_fname_str_dbg(smb_fname_src),
6205 smb_fname_str_dbg(smb_fname_dst),
6206 smb_fname_dst->original_lcomp));
6208 /* The dest name still may have wildcards. */
6209 if (dest_has_wild) {
6210 char *fname_dst_mod = NULL;
6211 if (!resolve_wildcards(smb_fname_dst,
6212 smb_fname_src->base_name,
6213 smb_fname_dst->base_name,
6215 DEBUG(6, ("rename_internals: resolve_wildcards "
6217 smb_fname_src->base_name,
6218 smb_fname_dst->base_name));
6219 status = NT_STATUS_NO_MEMORY;
6222 TALLOC_FREE(smb_fname_dst->base_name);
6223 smb_fname_dst->base_name = fname_dst_mod;
6226 ZERO_STRUCT(smb_fname_src->st);
6227 if (posix_pathnames) {
6228 SMB_VFS_LSTAT(conn, smb_fname_src);
6230 SMB_VFS_STAT(conn, smb_fname_src);
6233 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6234 create_options |= FILE_DIRECTORY_FILE;
6237 status = SMB_VFS_CREATE_FILE(
6240 0, /* root_dir_fid */
6241 smb_fname_src, /* fname */
6242 access_mask, /* access_mask */
6243 (FILE_SHARE_READ | /* share_access */
6245 FILE_OPEN, /* create_disposition*/
6246 create_options, /* create_options */
6247 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6248 0, /* oplock_request */
6249 0, /* allocation_size */
6255 if (!NT_STATUS_IS_OK(status)) {
6256 DEBUG(3, ("Could not open rename source %s: %s\n",
6257 smb_fname_str_dbg(smb_fname_src),
6258 nt_errstr(status)));
6262 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6263 attrs, replace_if_exists);
6265 close_file(req, fsp, NORMAL_CLOSE);
6267 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6268 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6269 smb_fname_str_dbg(smb_fname_dst)));
6275 * Wildcards - process each file that matches.
6277 if (strequal(fname_src_mask, "????????.???")) {
6278 TALLOC_FREE(fname_src_mask);
6279 fname_src_mask = talloc_strdup(ctx, "*");
6280 if (!fname_src_mask) {
6281 status = NT_STATUS_NO_MEMORY;
6286 status = check_name(conn, fname_src_dir);
6287 if (!NT_STATUS_IS_OK(status)) {
6291 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6293 if (dir_hnd == NULL) {
6294 status = map_nt_error_from_unix(errno);
6298 status = NT_STATUS_NO_SUCH_FILE;
6300 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6301 * - gentest fix. JRA
6304 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
6305 files_struct *fsp = NULL;
6306 char *destname = NULL;
6307 bool sysdir_entry = False;
6309 /* Quick check for "." and ".." */
6310 if (ISDOT(dname) || ISDOTDOT(dname)) {
6312 sysdir_entry = True;
6318 if (!is_visible_file(conn, fname_src_dir, dname,
6319 &smb_fname_src->st, false)) {
6323 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6328 status = NT_STATUS_OBJECT_NAME_INVALID;
6332 TALLOC_FREE(smb_fname_src->base_name);
6333 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6337 if (!smb_fname_src->base_name) {
6338 status = NT_STATUS_NO_MEMORY;
6342 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6343 smb_fname_dst->base_name,
6345 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6346 smb_fname_src->base_name, destname));
6350 status = NT_STATUS_NO_MEMORY;
6354 TALLOC_FREE(smb_fname_dst->base_name);
6355 smb_fname_dst->base_name = destname;
6357 ZERO_STRUCT(smb_fname_src->st);
6358 if (posix_pathnames) {
6359 SMB_VFS_LSTAT(conn, smb_fname_src);
6361 SMB_VFS_STAT(conn, smb_fname_src);
6366 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6367 create_options |= FILE_DIRECTORY_FILE;
6370 status = SMB_VFS_CREATE_FILE(
6373 0, /* root_dir_fid */
6374 smb_fname_src, /* fname */
6375 access_mask, /* access_mask */
6376 (FILE_SHARE_READ | /* share_access */
6378 FILE_OPEN, /* create_disposition*/
6379 create_options, /* create_options */
6380 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6381 0, /* oplock_request */
6382 0, /* allocation_size */
6388 if (!NT_STATUS_IS_OK(status)) {
6389 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6390 "returned %s rename %s -> %s\n",
6392 smb_fname_str_dbg(smb_fname_src),
6393 smb_fname_str_dbg(smb_fname_dst)));
6397 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6399 if (!smb_fname_dst->original_lcomp) {
6400 status = NT_STATUS_NO_MEMORY;
6404 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6405 attrs, replace_if_exists);
6407 close_file(req, fsp, NORMAL_CLOSE);
6409 if (!NT_STATUS_IS_OK(status)) {
6410 DEBUG(3, ("rename_internals_fsp returned %s for "
6411 "rename %s -> %s\n", nt_errstr(status),
6412 smb_fname_str_dbg(smb_fname_src),
6413 smb_fname_str_dbg(smb_fname_dst)));
6419 DEBUG(3,("rename_internals: doing rename on %s -> "
6420 "%s\n", smb_fname_str_dbg(smb_fname_src),
6421 smb_fname_str_dbg(smb_fname_src)));
6424 TALLOC_FREE(dir_hnd);
6426 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6427 status = map_nt_error_from_unix(errno);
6431 TALLOC_FREE(smb_fname_src);
6432 TALLOC_FREE(smb_fname_dst);
6433 TALLOC_FREE(fname_src_dir);
6434 TALLOC_FREE(fname_src_mask);
6438 /****************************************************************************
6440 ****************************************************************************/
6442 void reply_mv(struct smb_request *req)
6444 connection_struct *conn = req->conn;
6446 char *newname = NULL;
6450 bool src_has_wcard = False;
6451 bool dest_has_wcard = False;
6452 TALLOC_CTX *ctx = talloc_tos();
6454 START_PROFILE(SMBmv);
6457 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6462 attrs = SVAL(req->vwv+0, 0);
6464 p = (const char *)req->buf + 1;
6465 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6466 &status, &src_has_wcard);
6467 if (!NT_STATUS_IS_OK(status)) {
6468 reply_nterror(req, status);
6473 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6474 &status, &dest_has_wcard);
6475 if (!NT_STATUS_IS_OK(status)) {
6476 reply_nterror(req, status);
6481 status = resolve_dfspath_wcard(ctx, conn,
6482 req->flags2 & FLAGS2_DFS_PATHNAMES,
6486 if (!NT_STATUS_IS_OK(status)) {
6487 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6488 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6489 ERRSRV, ERRbadpath);
6493 reply_nterror(req, status);
6498 status = resolve_dfspath_wcard(ctx, conn,
6499 req->flags2 & FLAGS2_DFS_PATHNAMES,
6503 if (!NT_STATUS_IS_OK(status)) {
6504 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6505 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6506 ERRSRV, ERRbadpath);
6510 reply_nterror(req, status);
6515 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6517 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6518 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6519 if (!NT_STATUS_IS_OK(status)) {
6520 if (open_was_deferred(req->mid)) {
6521 /* We have re-scheduled this call. */
6525 reply_nterror(req, status);
6530 reply_outbuf(req, 0, 0);
6536 /*******************************************************************
6537 Copy a file as part of a reply_copy.
6538 ******************************************************************/
6541 * TODO: check error codes on all callers
6544 NTSTATUS copy_file(TALLOC_CTX *ctx,
6545 connection_struct *conn,
6546 struct smb_filename *smb_fname_src,
6547 struct smb_filename *smb_fname_dst,
6550 bool target_is_directory)
6552 struct smb_filename *smb_fname_dst_tmp = NULL;
6553 char *fname_src = NULL;
6555 files_struct *fsp1,*fsp2;
6557 uint32 new_create_disposition;
6561 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6562 if (!NT_STATUS_IS_OK(status)) {
6567 * If the target is a directory, extract the last component from the
6568 * src filename and append it to the dst filename
6570 if (target_is_directory) {
6573 /* dest/target can't be a stream if it's a directory. */
6574 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6576 p = strrchr_m(smb_fname_src->base_name,'/');
6580 p = smb_fname_src->base_name;
6582 smb_fname_dst_tmp->base_name =
6583 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6585 if (!smb_fname_dst_tmp->base_name) {
6586 status = NT_STATUS_NO_MEMORY;
6591 status = vfs_file_exist(conn, smb_fname_src);
6592 if (!NT_STATUS_IS_OK(status)) {
6596 if (!target_is_directory && count) {
6597 new_create_disposition = FILE_OPEN;
6599 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6600 0, ofun, NULL, NULL,
6601 &new_create_disposition,
6603 status = NT_STATUS_INVALID_PARAMETER;
6608 /* Open the src file for reading. */
6609 status = SMB_VFS_CREATE_FILE(
6612 0, /* root_dir_fid */
6613 smb_fname_src, /* fname */
6614 FILE_GENERIC_READ, /* access_mask */
6615 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6616 FILE_OPEN, /* create_disposition*/
6617 0, /* create_options */
6618 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6619 INTERNAL_OPEN_ONLY, /* oplock_request */
6620 0, /* allocation_size */
6626 if (!NT_STATUS_IS_OK(status)) {
6630 status = get_full_smb_filename(talloc_tos(), smb_fname_src, &fname_src);
6631 if (!NT_STATUS_IS_OK(status)) {
6635 dosattrs = dos_mode(conn, fname_src, &smb_fname_src->st);
6637 TALLOC_FREE(fname_src);
6639 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6640 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6643 /* Open the dst file for writing. */
6644 status = SMB_VFS_CREATE_FILE(
6647 0, /* root_dir_fid */
6648 smb_fname_dst, /* fname */
6649 FILE_GENERIC_WRITE, /* access_mask */
6650 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6651 new_create_disposition, /* create_disposition*/
6652 0, /* create_options */
6653 dosattrs, /* file_attributes */
6654 INTERNAL_OPEN_ONLY, /* oplock_request */
6655 0, /* allocation_size */
6661 if (!NT_STATUS_IS_OK(status)) {
6662 close_file(NULL, fsp1, ERROR_CLOSE);
6666 if ((ofun&3) == 1) {
6667 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6668 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6670 * Stop the copy from occurring.
6673 smb_fname_src->st.st_ex_size = 0;
6677 /* Do the actual copy. */
6678 if (smb_fname_src->st.st_ex_size) {
6679 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6682 close_file(NULL, fsp1, NORMAL_CLOSE);
6684 /* Ensure the modtime is set correctly on the destination file. */
6685 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6688 * As we are opening fsp1 read-only we only expect
6689 * an error on close on fsp2 if we are out of space.
6690 * Thus we don't look at the error return from the
6693 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6695 if (!NT_STATUS_IS_OK(status)) {
6699 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6700 status = NT_STATUS_DISK_FULL;
6704 status = NT_STATUS_OK;
6707 TALLOC_FREE(smb_fname_dst_tmp);
6711 /****************************************************************************
6712 Reply to a file copy.
6713 ****************************************************************************/
6715 void reply_copy(struct smb_request *req)
6717 connection_struct *conn = req->conn;
6718 struct smb_filename *smb_fname_src = NULL;
6719 struct smb_filename *smb_fname_dst = NULL;
6720 char *fname_src = NULL;
6721 char *fname_dst = NULL;
6722 char *fname_src_mask = NULL;
6723 char *fname_src_dir = NULL;
6726 int error = ERRnoaccess;
6731 bool target_is_directory=False;
6732 bool source_has_wild = False;
6733 bool dest_has_wild = False;
6735 TALLOC_CTX *ctx = talloc_tos();
6737 START_PROFILE(SMBcopy);
6740 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6744 tid2 = SVAL(req->vwv+0, 0);
6745 ofun = SVAL(req->vwv+1, 0);
6746 flags = SVAL(req->vwv+2, 0);
6748 p = (const char *)req->buf;
6749 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6750 &status, &source_has_wild);
6751 if (!NT_STATUS_IS_OK(status)) {
6752 reply_nterror(req, status);
6755 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6756 &status, &dest_has_wild);
6757 if (!NT_STATUS_IS_OK(status)) {
6758 reply_nterror(req, status);
6762 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6764 if (tid2 != conn->cnum) {
6765 /* can't currently handle inter share copies XXXX */
6766 DEBUG(3,("Rejecting inter-share copy\n"));
6767 reply_doserror(req, ERRSRV, ERRinvdevice);
6771 status = resolve_dfspath_wcard(ctx, conn,
6772 req->flags2 & FLAGS2_DFS_PATHNAMES,
6776 if (!NT_STATUS_IS_OK(status)) {
6777 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6778 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6779 ERRSRV, ERRbadpath);
6782 reply_nterror(req, status);
6786 status = resolve_dfspath_wcard(ctx, conn,
6787 req->flags2 & FLAGS2_DFS_PATHNAMES,
6791 if (!NT_STATUS_IS_OK(status)) {
6792 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6793 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6794 ERRSRV, ERRbadpath);
6797 reply_nterror(req, status);
6801 status = unix_convert(ctx, conn, fname_src, &smb_fname_src,
6802 source_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6803 if (!NT_STATUS_IS_OK(status)) {
6804 reply_nterror(req, status);
6808 status = unix_convert(ctx, conn, fname_dst, &smb_fname_dst,
6809 dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6810 if (!NT_STATUS_IS_OK(status)) {
6811 reply_nterror(req, status);
6815 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6817 if ((flags&1) && target_is_directory) {
6818 reply_doserror(req, ERRDOS, ERRbadfile);
6822 if ((flags&2) && !target_is_directory) {
6823 reply_doserror(req, ERRDOS, ERRbadpath);
6827 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6828 /* wants a tree copy! XXXX */
6829 DEBUG(3,("Rejecting tree copy\n"));
6830 reply_doserror(req, ERRSRV, ERRerror);
6834 /* Split up the directory from the filename/mask. */
6835 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6836 &fname_src_dir, &fname_src_mask);
6837 if (!NT_STATUS_IS_OK(status)) {
6838 reply_nterror(req, NT_STATUS_NO_MEMORY);
6843 * We should only check the mangled cache
6844 * here if unix_convert failed. This means
6845 * that the path in 'mask' doesn't exist
6846 * on the file system and so we need to look
6847 * for a possible mangle. This patch from
6848 * Tine Smukavec <valentin.smukavec@hermes.si>.
6850 if (!VALID_STAT(smb_fname_src->st) &&
6851 mangle_is_mangled(fname_src_mask, conn->params)) {
6852 char *new_mask = NULL;
6853 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6854 &new_mask, conn->params);
6856 /* Use demangled name if one was successfully found. */
6858 TALLOC_FREE(fname_src_mask);
6859 fname_src_mask = new_mask;
6863 if (!source_has_wild) {
6866 * Only one file needs to be copied. Append the mask back onto
6869 TALLOC_FREE(smb_fname_src->base_name);
6870 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6874 if (!smb_fname_src->base_name) {
6875 reply_nterror(req, NT_STATUS_NO_MEMORY);
6879 if (dest_has_wild) {
6880 char *fname_dst_mod = NULL;
6881 if (!resolve_wildcards(smb_fname_dst,
6882 smb_fname_src->base_name,
6883 smb_fname_dst->base_name,
6885 reply_nterror(req, NT_STATUS_NO_MEMORY);
6888 TALLOC_FREE(smb_fname_dst->base_name);
6889 smb_fname_dst->base_name = fname_dst_mod;
6892 status = check_name(conn, smb_fname_src->base_name);
6893 if (!NT_STATUS_IS_OK(status)) {
6894 reply_nterror(req, status);
6898 status = check_name(conn, smb_fname_dst->base_name);
6899 if (!NT_STATUS_IS_OK(status)) {
6900 reply_nterror(req, status);
6904 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6905 ofun, count, target_is_directory);
6907 if(!NT_STATUS_IS_OK(status)) {
6908 reply_nterror(req, status);
6914 struct smb_Dir *dir_hnd = NULL;
6915 const char *dname = NULL;
6919 * There is a wildcard that requires us to actually read the
6920 * src dir and copy each file matching the mask to the dst.
6921 * Right now streams won't be copied, but this could
6922 * presumably be added with a nested loop for reach dir entry.
6924 SMB_ASSERT(!smb_fname_src->stream_name);
6925 SMB_ASSERT(!smb_fname_dst->stream_name);
6927 smb_fname_src->stream_name = NULL;
6928 smb_fname_dst->stream_name = NULL;
6930 if (strequal(fname_src_mask,"????????.???")) {
6931 TALLOC_FREE(fname_src_mask);
6932 fname_src_mask = talloc_strdup(ctx, "*");
6933 if (!fname_src_mask) {
6934 reply_nterror(req, NT_STATUS_NO_MEMORY);
6939 status = check_name(conn, fname_src_dir);
6940 if (!NT_STATUS_IS_OK(status)) {
6941 reply_nterror(req, status);
6945 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6946 if (dir_hnd == NULL) {
6947 status = map_nt_error_from_unix(errno);
6948 reply_nterror(req, status);
6954 /* Iterate over the src dir copying each entry to the dst. */
6955 while ((dname = ReadDirName(dir_hnd, &offset,
6956 &smb_fname_src->st))) {
6957 char *destname = NULL;
6959 if (ISDOT(dname) || ISDOTDOT(dname)) {
6963 if (!is_visible_file(conn, fname_src_dir, dname,
6964 &smb_fname_src->st, false)) {
6968 if(!mask_match(dname, fname_src_mask,
6969 conn->case_sensitive)) {
6973 error = ERRnoaccess;
6975 /* Get the src smb_fname struct setup. */
6976 TALLOC_FREE(smb_fname_src->base_name);
6977 smb_fname_src->base_name =
6978 talloc_asprintf(smb_fname_src, "%s/%s",
6979 fname_src_dir, dname);
6981 if (!smb_fname_src->base_name) {
6982 TALLOC_FREE(dir_hnd);
6983 reply_nterror(req, NT_STATUS_NO_MEMORY);
6987 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6988 smb_fname_dst->base_name,
6993 TALLOC_FREE(dir_hnd);
6994 reply_nterror(req, NT_STATUS_NO_MEMORY);
6998 TALLOC_FREE(smb_fname_dst->base_name);
6999 smb_fname_dst->base_name = destname;
7001 status = check_name(conn, smb_fname_src->base_name);
7002 if (!NT_STATUS_IS_OK(status)) {
7003 TALLOC_FREE(dir_hnd);
7004 reply_nterror(req, status);
7008 status = check_name(conn, smb_fname_dst->base_name);
7009 if (!NT_STATUS_IS_OK(status)) {
7010 TALLOC_FREE(dir_hnd);
7011 reply_nterror(req, status);
7015 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7016 smb_fname_src->base_name,
7017 smb_fname_dst->base_name));
7019 status = copy_file(ctx, conn, smb_fname_src,
7020 smb_fname_dst, ofun, count,
7021 target_is_directory);
7022 if (NT_STATUS_IS_OK(status)) {
7026 TALLOC_FREE(dir_hnd);
7031 /* Error on close... */
7033 reply_unixerror(req, ERRHRD, ERRgeneral);
7037 reply_doserror(req, ERRDOS, error);
7041 reply_outbuf(req, 1, 0);
7042 SSVAL(req->outbuf,smb_vwv0,count);
7044 TALLOC_FREE(smb_fname_src);
7045 TALLOC_FREE(smb_fname_dst);
7046 TALLOC_FREE(fname_src);
7047 TALLOC_FREE(fname_dst);
7048 TALLOC_FREE(fname_src_mask);
7049 TALLOC_FREE(fname_src_dir);
7051 END_PROFILE(SMBcopy);
7056 #define DBGC_CLASS DBGC_LOCKING
7058 /****************************************************************************
7059 Get a lock pid, dealing with large count requests.
7060 ****************************************************************************/
7062 uint32 get_lock_pid(const uint8_t *data, int data_offset,
7063 bool large_file_format)
7065 if(!large_file_format)
7066 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
7068 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7071 /****************************************************************************
7072 Get a lock count, dealing with large count requests.
7073 ****************************************************************************/
7075 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7076 bool large_file_format)
7080 if(!large_file_format) {
7081 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7084 #if defined(HAVE_LONGLONG)
7085 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7086 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7087 #else /* HAVE_LONGLONG */
7090 * NT4.x seems to be broken in that it sends large file (64 bit)
7091 * lockingX calls even if the CAP_LARGE_FILES was *not*
7092 * negotiated. For boxes without large unsigned ints truncate the
7093 * lock count by dropping the top 32 bits.
7096 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7097 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7098 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7099 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7100 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7103 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7104 #endif /* HAVE_LONGLONG */
7110 #if !defined(HAVE_LONGLONG)
7111 /****************************************************************************
7112 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7113 ****************************************************************************/
7115 static uint32 map_lock_offset(uint32 high, uint32 low)
7119 uint32 highcopy = high;
7122 * Try and find out how many significant bits there are in high.
7125 for(i = 0; highcopy; i++)
7129 * We use 31 bits not 32 here as POSIX
7130 * lock offsets may not be negative.
7133 mask = (~0) << (31 - i);
7136 return 0; /* Fail. */
7142 #endif /* !defined(HAVE_LONGLONG) */
7144 /****************************************************************************
7145 Get a lock offset, dealing with large offset requests.
7146 ****************************************************************************/
7148 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7149 bool large_file_format, bool *err)
7151 uint64_t offset = 0;
7155 if(!large_file_format) {
7156 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7159 #if defined(HAVE_LONGLONG)
7160 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7161 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7162 #else /* HAVE_LONGLONG */
7165 * NT4.x seems to be broken in that it sends large file (64 bit)
7166 * lockingX calls even if the CAP_LARGE_FILES was *not*
7167 * negotiated. For boxes without large unsigned ints mangle the
7168 * lock offset by mapping the top 32 bits onto the lower 32.
7171 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7172 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7173 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7176 if((new_low = map_lock_offset(high, low)) == 0) {
7178 return (uint64_t)-1;
7181 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7182 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7183 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7184 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7187 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7188 #endif /* HAVE_LONGLONG */
7194 /****************************************************************************
7195 Reply to a lockingX request.
7196 ****************************************************************************/
7198 void reply_lockingX(struct smb_request *req)
7200 connection_struct *conn = req->conn;
7202 unsigned char locktype;
7203 unsigned char oplocklevel;
7206 uint64_t count = 0, offset = 0;
7210 const uint8_t *data;
7211 bool large_file_format;
7213 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7215 START_PROFILE(SMBlockingX);
7218 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7219 END_PROFILE(SMBlockingX);
7223 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7224 locktype = CVAL(req->vwv+3, 0);
7225 oplocklevel = CVAL(req->vwv+3, 1);
7226 num_ulocks = SVAL(req->vwv+6, 0);
7227 num_locks = SVAL(req->vwv+7, 0);
7228 lock_timeout = IVAL(req->vwv+4, 0);
7229 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7231 if (!check_fsp(conn, req, fsp)) {
7232 END_PROFILE(SMBlockingX);
7238 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7239 /* we don't support these - and CANCEL_LOCK makes w2k
7240 and XP reboot so I don't really want to be
7241 compatible! (tridge) */
7242 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7243 END_PROFILE(SMBlockingX);
7247 /* Check if this is an oplock break on a file
7248 we have granted an oplock on.
7250 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7251 /* Client can insist on breaking to none. */
7252 bool break_to_none = (oplocklevel == 0);
7255 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7256 "for fnum = %d\n", (unsigned int)oplocklevel,
7260 * Make sure we have granted an exclusive or batch oplock on
7264 if (fsp->oplock_type == 0) {
7266 /* The Samba4 nbench simulator doesn't understand
7267 the difference between break to level2 and break
7268 to none from level2 - it sends oplock break
7269 replies in both cases. Don't keep logging an error
7270 message here - just ignore it. JRA. */
7272 DEBUG(5,("reply_lockingX: Error : oplock break from "
7273 "client for fnum = %d (oplock=%d) and no "
7274 "oplock granted on this file (%s).\n",
7275 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
7277 /* if this is a pure oplock break request then don't
7279 if (num_locks == 0 && num_ulocks == 0) {
7280 END_PROFILE(SMBlockingX);
7283 END_PROFILE(SMBlockingX);
7284 reply_doserror(req, ERRDOS, ERRlock);
7289 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7291 result = remove_oplock(fsp);
7293 result = downgrade_oplock(fsp);
7297 DEBUG(0, ("reply_lockingX: error in removing "
7298 "oplock on file %s\n", fsp->fsp_name));
7299 /* Hmmm. Is this panic justified? */
7300 smb_panic("internal tdb error");
7303 reply_to_oplock_break_requests(fsp);
7305 /* if this is a pure oplock break request then don't send a
7307 if (num_locks == 0 && num_ulocks == 0) {
7308 /* Sanity check - ensure a pure oplock break is not a
7310 if(CVAL(req->vwv+0, 0) != 0xff)
7311 DEBUG(0,("reply_lockingX: Error : pure oplock "
7312 "break is a chained %d request !\n",
7313 (unsigned int)CVAL(req->vwv+0, 0)));
7314 END_PROFILE(SMBlockingX);
7320 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7321 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7322 END_PROFILE(SMBlockingX);
7326 /* Data now points at the beginning of the list
7327 of smb_unlkrng structs */
7328 for(i = 0; i < (int)num_ulocks; i++) {
7329 lock_pid = get_lock_pid( data, i, large_file_format);
7330 count = get_lock_count( data, i, large_file_format);
7331 offset = get_lock_offset( data, i, large_file_format, &err);
7334 * There is no error code marked "stupid client bug".... :-).
7337 END_PROFILE(SMBlockingX);
7338 reply_doserror(req, ERRDOS, ERRnoaccess);
7342 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
7343 "pid %u, file %s\n", (double)offset, (double)count,
7344 (unsigned int)lock_pid, fsp->fsp_name ));
7346 status = do_unlock(smbd_messaging_context(),
7353 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
7354 nt_errstr(status)));
7356 if (NT_STATUS_V(status)) {
7357 END_PROFILE(SMBlockingX);
7358 reply_nterror(req, status);
7363 /* Setup the timeout in seconds. */
7365 if (!lp_blocking_locks(SNUM(conn))) {
7369 /* Now do any requested locks */
7370 data += ((large_file_format ? 20 : 10)*num_ulocks);
7372 /* Data now points at the beginning of the list
7373 of smb_lkrng structs */
7375 for(i = 0; i < (int)num_locks; i++) {
7376 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
7377 READ_LOCK:WRITE_LOCK);
7378 lock_pid = get_lock_pid( data, i, large_file_format);
7379 count = get_lock_count( data, i, large_file_format);
7380 offset = get_lock_offset( data, i, large_file_format, &err);
7383 * There is no error code marked "stupid client bug".... :-).
7386 END_PROFILE(SMBlockingX);
7387 reply_doserror(req, ERRDOS, ERRnoaccess);
7391 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
7392 "%u, file %s timeout = %d\n", (double)offset,
7393 (double)count, (unsigned int)lock_pid,
7394 fsp->fsp_name, (int)lock_timeout ));
7396 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7397 struct blocking_lock_record *blr = NULL;
7399 if (lp_blocking_locks(SNUM(conn))) {
7401 /* Schedule a message to ourselves to
7402 remove the blocking lock record and
7403 return the right error. */
7405 blr = blocking_lock_cancel(fsp,
7411 NT_STATUS_FILE_LOCK_CONFLICT);
7413 END_PROFILE(SMBlockingX);
7418 ERRcancelviolation));
7422 /* Remove a matching pending lock. */
7423 status = do_lock_cancel(fsp,
7430 bool blocking_lock = lock_timeout ? True : False;
7431 bool defer_lock = False;
7432 struct byte_range_lock *br_lck;
7433 uint32 block_smbpid;
7435 br_lck = do_lock(smbd_messaging_context(),
7447 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7448 /* Windows internal resolution for blocking locks seems
7449 to be about 200ms... Don't wait for less than that. JRA. */
7450 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7451 lock_timeout = lp_lock_spin_time();
7456 /* This heuristic seems to match W2K3 very well. If a
7457 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7458 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7459 far as I can tell. Replacement for do_lock_spin(). JRA. */
7461 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7462 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7464 lock_timeout = lp_lock_spin_time();
7467 if (br_lck && defer_lock) {
7469 * A blocking lock was requested. Package up
7470 * this smb into a queued request and push it
7471 * onto the blocking lock queue.
7473 if(push_blocking_lock_request(br_lck,
7484 TALLOC_FREE(br_lck);
7485 END_PROFILE(SMBlockingX);
7490 TALLOC_FREE(br_lck);
7493 if (NT_STATUS_V(status)) {
7498 /* If any of the above locks failed, then we must unlock
7499 all of the previous locks (X/Open spec). */
7500 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7502 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7503 i = -1; /* we want to skip the for loop */
7507 * Ensure we don't do a remove on the lock that just failed,
7508 * as under POSIX rules, if we have a lock already there, we
7509 * will delete it (and we shouldn't) .....
7511 for(i--; i >= 0; i--) {
7512 lock_pid = get_lock_pid( data, i, large_file_format);
7513 count = get_lock_count( data, i, large_file_format);
7514 offset = get_lock_offset( data, i, large_file_format,
7518 * There is no error code marked "stupid client
7522 END_PROFILE(SMBlockingX);
7523 reply_doserror(req, ERRDOS, ERRnoaccess);
7527 do_unlock(smbd_messaging_context(),
7534 END_PROFILE(SMBlockingX);
7535 reply_nterror(req, status);
7539 reply_outbuf(req, 2, 0);
7541 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7542 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7544 END_PROFILE(SMBlockingX);
7549 #define DBGC_CLASS DBGC_ALL
7551 /****************************************************************************
7552 Reply to a SMBreadbmpx (read block multiplex) request.
7553 Always reply with an error, if someone has a platform really needs this,
7554 please contact vl@samba.org
7555 ****************************************************************************/
7557 void reply_readbmpx(struct smb_request *req)
7559 START_PROFILE(SMBreadBmpx);
7560 reply_doserror(req, ERRSRV, ERRuseSTD);
7561 END_PROFILE(SMBreadBmpx);
7565 /****************************************************************************
7566 Reply to a SMBreadbs (read block multiplex secondary) request.
7567 Always reply with an error, if someone has a platform really needs this,
7568 please contact vl@samba.org
7569 ****************************************************************************/
7571 void reply_readbs(struct smb_request *req)
7573 START_PROFILE(SMBreadBs);
7574 reply_doserror(req, ERRSRV, ERRuseSTD);
7575 END_PROFILE(SMBreadBs);
7579 /****************************************************************************
7580 Reply to a SMBsetattrE.
7581 ****************************************************************************/
7583 void reply_setattrE(struct smb_request *req)
7585 connection_struct *conn = req->conn;
7586 struct smb_filename *smb_fname = NULL;
7587 struct smb_file_time ft;
7591 START_PROFILE(SMBsetattrE);
7595 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7599 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7601 if(!fsp || (fsp->conn != conn)) {
7602 reply_doserror(req, ERRDOS, ERRbadfid);
7606 /* XXX: Remove when fsp->fsp_name is converted to smb_filename. */
7607 status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name,
7609 if (!NT_STATUS_IS_OK(status)) {
7610 reply_nterror(req, status);
7615 * Convert the DOS times into unix times.
7618 ft.atime = convert_time_t_to_timespec(
7619 srv_make_unix_date2(req->vwv+3));
7620 ft.mtime = convert_time_t_to_timespec(
7621 srv_make_unix_date2(req->vwv+5));
7622 ft.create_time = convert_time_t_to_timespec(
7623 srv_make_unix_date2(req->vwv+1));
7625 reply_outbuf(req, 0, 0);
7628 * Patch from Ray Frush <frush@engr.colostate.edu>
7629 * Sometimes times are sent as zero - ignore them.
7632 /* Ensure we have a valid stat struct for the source. */
7633 if (fsp->fh->fd != -1) {
7634 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) == -1) {
7635 status = map_nt_error_from_unix(errno);
7636 reply_nterror(req, status);
7642 if (fsp->posix_open) {
7643 ret = SMB_VFS_LSTAT(conn, smb_fname);
7645 ret = SMB_VFS_STAT(conn, smb_fname);
7648 status = map_nt_error_from_unix(errno);
7649 reply_nterror(req, status);
7654 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7655 if (!NT_STATUS_IS_OK(status)) {
7656 reply_doserror(req, ERRDOS, ERRnoaccess);
7660 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7663 (unsigned int)ft.atime.tv_sec,
7664 (unsigned int)ft.mtime.tv_sec,
7665 (unsigned int)ft.create_time.tv_sec
7668 END_PROFILE(SMBsetattrE);
7673 /* Back from the dead for OS/2..... JRA. */
7675 /****************************************************************************
7676 Reply to a SMBwritebmpx (write block multiplex primary) request.
7677 Always reply with an error, if someone has a platform really needs this,
7678 please contact vl@samba.org
7679 ****************************************************************************/
7681 void reply_writebmpx(struct smb_request *req)
7683 START_PROFILE(SMBwriteBmpx);
7684 reply_doserror(req, ERRSRV, ERRuseSTD);
7685 END_PROFILE(SMBwriteBmpx);
7689 /****************************************************************************
7690 Reply to a SMBwritebs (write block multiplex secondary) request.
7691 Always reply with an error, if someone has a platform really needs this,
7692 please contact vl@samba.org
7693 ****************************************************************************/
7695 void reply_writebs(struct smb_request *req)
7697 START_PROFILE(SMBwriteBs);
7698 reply_doserror(req, ERRSRV, ERRuseSTD);
7699 END_PROFILE(SMBwriteBs);
7703 /****************************************************************************
7704 Reply to a SMBgetattrE.
7705 ****************************************************************************/
7707 void reply_getattrE(struct smb_request *req)
7709 connection_struct *conn = req->conn;
7710 SMB_STRUCT_STAT sbuf;
7713 struct timespec create_ts;
7715 START_PROFILE(SMBgetattrE);
7718 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7719 END_PROFILE(SMBgetattrE);
7723 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7725 if(!fsp || (fsp->conn != conn)) {
7726 reply_doserror(req, ERRDOS, ERRbadfid);
7727 END_PROFILE(SMBgetattrE);
7731 /* Do an fstat on this file */
7732 if(fsp_stat(fsp, &sbuf)) {
7733 reply_unixerror(req, ERRDOS, ERRnoaccess);
7734 END_PROFILE(SMBgetattrE);
7738 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7741 * Convert the times into dos times. Set create
7742 * date to be last modify date as UNIX doesn't save
7746 reply_outbuf(req, 11, 0);
7748 create_ts = sbuf.st_ex_btime;
7749 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7750 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7751 convert_timespec_to_time_t(sbuf.st_ex_atime));
7752 /* Should we check pending modtime here ? JRA */
7753 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7754 convert_timespec_to_time_t(sbuf.st_ex_mtime));
7757 SIVAL(req->outbuf, smb_vwv6, 0);
7758 SIVAL(req->outbuf, smb_vwv8, 0);
7760 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7761 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_ex_size);
7762 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7764 SSVAL(req->outbuf,smb_vwv10, mode);
7766 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7768 END_PROFILE(SMBgetattrE);