2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "smbd/globals.h"
30 extern enum protocol_types Protocol;
32 /****************************************************************************
33 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
34 path or anything including wildcards.
35 We're assuming here that '/' is not the second byte in any multibyte char
36 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
38 ****************************************************************************/
40 /* Custom version for processing POSIX paths. */
41 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
43 static NTSTATUS check_path_syntax_internal(char *path,
45 bool *p_last_component_contains_wcard)
49 NTSTATUS ret = NT_STATUS_OK;
50 bool start_of_name_component = True;
51 bool stream_started = false;
53 *p_last_component_contains_wcard = False;
60 return NT_STATUS_OBJECT_NAME_INVALID;
63 return NT_STATUS_OBJECT_NAME_INVALID;
65 if (strchr_m(&s[1], ':')) {
66 return NT_STATUS_OBJECT_NAME_INVALID;
68 if (StrCaseCmp(s, ":$DATA") != 0) {
69 return NT_STATUS_INVALID_PARAMETER;
75 if (!posix_path && !stream_started && *s == ':') {
76 if (*p_last_component_contains_wcard) {
77 return NT_STATUS_OBJECT_NAME_INVALID;
79 /* Stream names allow more characters than file names.
80 We're overloading posix_path here to allow a wider
81 range of characters. If stream_started is true this
82 is still a Windows path even if posix_path is true.
85 stream_started = true;
86 start_of_name_component = false;
90 return NT_STATUS_OBJECT_NAME_INVALID;
94 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
96 * Safe to assume is not the second part of a mb char
97 * as this is handled below.
99 /* Eat multiple '/' or '\\' */
100 while (IS_PATH_SEP(*s,posix_path)) {
103 if ((d != path) && (*s != '\0')) {
104 /* We only care about non-leading or trailing '/' or '\\' */
108 start_of_name_component = True;
110 *p_last_component_contains_wcard = False;
114 if (start_of_name_component) {
115 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
116 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
119 * No mb char starts with '.' so we're safe checking the directory separator here.
122 /* If we just added a '/' - delete it */
123 if ((d > path) && (*(d-1) == '/')) {
128 /* Are we at the start ? Can't go back further if so. */
130 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
133 /* Go back one level... */
134 /* We know this is safe as '/' cannot be part of a mb sequence. */
135 /* NOTE - if this assumption is invalid we are not in good shape... */
136 /* Decrement d first as d points to the *next* char to write into. */
137 for (d--; d > path; d--) {
141 s += 2; /* Else go past the .. */
142 /* We're still at the start of a name component, just the previous one. */
145 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
157 if (*s <= 0x1f || *s == '|') {
158 return NT_STATUS_OBJECT_NAME_INVALID;
166 *p_last_component_contains_wcard = True;
175 /* Get the size of the next MB character. */
176 next_codepoint(s,&siz);
194 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
196 return NT_STATUS_INVALID_PARAMETER;
199 start_of_name_component = False;
207 /****************************************************************************
208 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
209 No wildcards allowed.
210 ****************************************************************************/
212 NTSTATUS check_path_syntax(char *path)
215 return check_path_syntax_internal(path, False, &ignore);
218 /****************************************************************************
219 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
220 Wildcards allowed - p_contains_wcard returns true if the last component contained
222 ****************************************************************************/
224 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
226 return check_path_syntax_internal(path, False, p_contains_wcard);
229 /****************************************************************************
230 Check the path for a POSIX client.
231 We're assuming here that '/' is not the second byte in any multibyte char
232 set (a safe assumption).
233 ****************************************************************************/
235 NTSTATUS check_path_syntax_posix(char *path)
238 return check_path_syntax_internal(path, True, &ignore);
241 /****************************************************************************
242 Pull a string and check the path allowing a wilcard - provide for error return.
243 ****************************************************************************/
245 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
246 const char *base_ptr,
253 bool *contains_wcard)
259 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
263 *err = NT_STATUS_INVALID_PARAMETER;
267 *contains_wcard = False;
269 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
271 * For a DFS path the function parse_dfs_path()
272 * will do the path processing, just make a copy.
278 if (lp_posix_pathnames()) {
279 *err = check_path_syntax_posix(*pp_dest);
281 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
287 /****************************************************************************
288 Pull a string and check the path - provide for error return.
289 ****************************************************************************/
291 size_t srvstr_get_path(TALLOC_CTX *ctx,
292 const char *base_ptr,
301 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
302 src_len, flags, err, &ignore);
305 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
306 char **pp_dest, const char *src, int flags,
307 NTSTATUS *err, bool *contains_wcard)
309 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
310 pp_dest, src, smbreq_bufrem(req, src),
311 flags, err, contains_wcard);
314 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
315 char **pp_dest, const char *src, int flags,
319 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
320 flags, err, &ignore);
323 /****************************************************************************
324 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
325 ****************************************************************************/
327 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
330 if (!(fsp) || !(conn)) {
331 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
334 if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
335 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
341 /****************************************************************************
342 Check if we have a correct fsp pointing to a file.
343 ****************************************************************************/
345 bool check_fsp(connection_struct *conn, struct smb_request *req,
348 if (!check_fsp_open(conn, req, fsp)) {
351 if ((fsp)->is_directory) {
352 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
355 if ((fsp)->fh->fd == -1) {
356 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
359 (fsp)->num_smb_operations++;
363 /****************************************************************************
364 Check if we have a correct fsp pointing to a quota fake file. Replacement for
365 the CHECK_NTQUOTA_HANDLE_OK macro.
366 ****************************************************************************/
368 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
371 if (!check_fsp_open(conn, req, fsp)) {
375 if (fsp->is_directory) {
379 if (fsp->fake_file_handle == NULL) {
383 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
387 if (fsp->fake_file_handle->private_data == NULL) {
394 /****************************************************************************
395 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
396 ****************************************************************************/
398 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
401 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
402 && (req->vuid == (fsp)->vuid)) {
406 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
410 static bool netbios_session_retarget(const char *name, int name_type)
413 char *trim_name_type;
414 const char *retarget_parm;
417 int retarget_type = 0x20;
418 int retarget_port = 139;
419 struct sockaddr_storage retarget_addr;
420 struct sockaddr_in *in_addr;
424 if (get_socket_port(smbd_server_fd()) != 139) {
428 trim_name = talloc_strdup(talloc_tos(), name);
429 if (trim_name == NULL) {
432 trim_char(trim_name, ' ', ' ');
434 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
436 if (trim_name_type == NULL) {
440 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
441 trim_name_type, NULL);
442 if (retarget_parm == NULL) {
443 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
446 if (retarget_parm == NULL) {
450 retarget = talloc_strdup(trim_name, retarget_parm);
451 if (retarget == NULL) {
455 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
457 p = strchr(retarget, ':');
460 retarget_port = atoi(p);
463 p = strchr_m(retarget, '#');
466 sscanf(p, "%x", &retarget_type);
469 ret = resolve_name(retarget, &retarget_addr, retarget_type);
471 DEBUG(10, ("could not resolve %s\n", retarget));
475 if (retarget_addr.ss_family != AF_INET) {
476 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
480 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
482 _smb_setlen(outbuf, 6);
483 SCVAL(outbuf, 0, 0x84);
484 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
485 *(uint16_t *)(outbuf+8) = htons(retarget_port);
487 if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
489 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
495 TALLOC_FREE(trim_name);
499 /****************************************************************************
500 Reply to a (netbios-level) special message.
501 ****************************************************************************/
503 void reply_special(char *inbuf)
505 int msg_type = CVAL(inbuf,0);
506 int msg_flags = CVAL(inbuf,1);
508 char name_type1, name_type2;
509 struct smbd_server_connection *sconn = smbd_server_conn;
512 * We only really use 4 bytes of the outbuf, but for the smb_setlen
513 * calculation & friends (srv_send_smb uses that) we need the full smb
516 char outbuf[smb_size];
520 memset(outbuf, '\0', sizeof(outbuf));
522 smb_setlen(outbuf,0);
525 case 0x81: /* session request */
527 if (sconn->nbt.got_session) {
528 exit_server_cleanly("multiple session request not permitted");
531 SCVAL(outbuf,0,0x82);
533 if (name_len(inbuf+4) > 50 ||
534 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
535 DEBUG(0,("Invalid name length in session request\n"));
538 name_type1 = name_extract(inbuf,4,name1);
539 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
540 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
541 name1, name_type1, name2, name_type2));
543 if (netbios_session_retarget(name1, name_type1)) {
544 exit_server_cleanly("retargeted client");
547 set_local_machine_name(name1, True);
548 set_remote_machine_name(name2, True);
550 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
551 get_local_machine_name(), get_remote_machine_name(),
554 if (name_type2 == 'R') {
555 /* We are being asked for a pathworks session ---
557 SCVAL(outbuf, 0,0x83);
561 /* only add the client's machine name to the list
562 of possibly valid usernames if we are operating
563 in share mode security */
564 if (lp_security() == SEC_SHARE) {
565 add_session_user(sconn, get_remote_machine_name());
568 reload_services(True);
571 sconn->nbt.got_session = true;
574 case 0x89: /* session keepalive request
575 (some old clients produce this?) */
576 SCVAL(outbuf,0,SMBkeepalive);
580 case 0x82: /* positive session response */
581 case 0x83: /* negative session response */
582 case 0x84: /* retarget session response */
583 DEBUG(0,("Unexpected session response\n"));
586 case SMBkeepalive: /* session keepalive */
591 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
592 msg_type, msg_flags));
594 srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
598 /****************************************************************************
600 conn POINTER CAN BE NULL HERE !
601 ****************************************************************************/
603 void reply_tcon(struct smb_request *req)
605 connection_struct *conn = req->conn;
607 char *service_buf = NULL;
608 char *password = NULL;
613 DATA_BLOB password_blob;
614 TALLOC_CTX *ctx = talloc_tos();
615 struct smbd_server_connection *sconn = smbd_server_conn;
617 START_PROFILE(SMBtcon);
619 if (req->buflen < 4) {
620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
621 END_PROFILE(SMBtcon);
625 p = (const char *)req->buf + 1;
626 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
628 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
630 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
633 if (service_buf == NULL || password == NULL || dev == NULL) {
634 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
635 END_PROFILE(SMBtcon);
638 p = strrchr_m(service_buf,'\\');
642 service = service_buf;
645 password_blob = data_blob(password, pwlen+1);
647 conn = make_connection(sconn,service,password_blob,dev,
648 req->vuid,&nt_status);
651 data_blob_clear_free(&password_blob);
654 reply_nterror(req, nt_status);
655 END_PROFILE(SMBtcon);
659 reply_outbuf(req, 2, 0);
660 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
661 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
662 SSVAL(req->outbuf,smb_tid,conn->cnum);
664 DEBUG(3,("tcon service=%s cnum=%d\n",
665 service, conn->cnum));
667 END_PROFILE(SMBtcon);
671 /****************************************************************************
672 Reply to a tcon and X.
673 conn POINTER CAN BE NULL HERE !
674 ****************************************************************************/
676 void reply_tcon_and_X(struct smb_request *req)
678 connection_struct *conn = req->conn;
679 const char *service = NULL;
681 TALLOC_CTX *ctx = talloc_tos();
682 /* what the cleint thinks the device is */
683 char *client_devicetype = NULL;
684 /* what the server tells the client the share represents */
685 const char *server_devicetype;
691 struct smbd_server_connection *sconn = smbd_server_conn;
693 START_PROFILE(SMBtconX);
696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
697 END_PROFILE(SMBtconX);
701 passlen = SVAL(req->vwv+3, 0);
702 tcon_flags = SVAL(req->vwv+2, 0);
704 /* we might have to close an old one */
705 if ((tcon_flags & 0x1) && conn) {
706 close_cnum(sconn, conn,req->vuid);
711 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
712 reply_doserror(req, ERRDOS, ERRbuftoosmall);
713 END_PROFILE(SMBtconX);
717 if (sconn->smb1.negprot.encrypted_passwords) {
718 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
719 if (lp_security() == SEC_SHARE) {
721 * Security = share always has a pad byte
722 * after the password.
724 p = (const char *)req->buf + passlen + 1;
726 p = (const char *)req->buf + passlen;
729 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
730 /* Ensure correct termination */
731 password.data[passlen]=0;
732 p = (const char *)req->buf + passlen + 1;
735 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
738 data_blob_clear_free(&password);
739 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
740 END_PROFILE(SMBtconX);
745 * the service name can be either: \\server\share
746 * or share directly like on the DELL PowerVault 705
749 q = strchr_m(path+2,'\\');
751 data_blob_clear_free(&password);
752 reply_doserror(req, ERRDOS, ERRnosuchshare);
753 END_PROFILE(SMBtconX);
761 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
762 &client_devicetype, p,
763 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
765 if (client_devicetype == NULL) {
766 data_blob_clear_free(&password);
767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
768 END_PROFILE(SMBtconX);
772 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
774 conn = make_connection(sconn, service, password, client_devicetype,
775 req->vuid, &nt_status);
778 data_blob_clear_free(&password);
781 reply_nterror(req, nt_status);
782 END_PROFILE(SMBtconX);
787 server_devicetype = "IPC";
788 else if ( IS_PRINT(conn) )
789 server_devicetype = "LPT1:";
791 server_devicetype = "A:";
793 if (Protocol < PROTOCOL_NT1) {
794 reply_outbuf(req, 2, 0);
795 if (message_push_string(&req->outbuf, server_devicetype,
796 STR_TERMINATE|STR_ASCII) == -1) {
797 reply_nterror(req, NT_STATUS_NO_MEMORY);
798 END_PROFILE(SMBtconX);
802 /* NT sets the fstype of IPC$ to the null string */
803 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
805 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
806 /* Return permissions. */
810 reply_outbuf(req, 7, 0);
813 perm1 = FILE_ALL_ACCESS;
814 perm2 = FILE_ALL_ACCESS;
816 perm1 = CAN_WRITE(conn) ?
821 SIVAL(req->outbuf, smb_vwv3, perm1);
822 SIVAL(req->outbuf, smb_vwv5, perm2);
824 reply_outbuf(req, 3, 0);
827 if ((message_push_string(&req->outbuf, server_devicetype,
828 STR_TERMINATE|STR_ASCII) == -1)
829 || (message_push_string(&req->outbuf, fstype,
830 STR_TERMINATE) == -1)) {
831 reply_nterror(req, NT_STATUS_NO_MEMORY);
832 END_PROFILE(SMBtconX);
836 /* what does setting this bit do? It is set by NT4 and
837 may affect the ability to autorun mounted cdroms */
838 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
839 (lp_csc_policy(SNUM(conn)) << 2));
841 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
842 DEBUG(2,("Serving %s as a Dfs root\n",
843 lp_servicename(SNUM(conn)) ));
844 SSVAL(req->outbuf, smb_vwv2,
845 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
850 DEBUG(3,("tconX service=%s \n",
853 /* set the incoming and outgoing tid to the just created one */
854 SSVAL(req->inbuf,smb_tid,conn->cnum);
855 SSVAL(req->outbuf,smb_tid,conn->cnum);
857 END_PROFILE(SMBtconX);
863 /****************************************************************************
864 Reply to an unknown type.
865 ****************************************************************************/
867 void reply_unknown_new(struct smb_request *req, uint8 type)
869 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
870 smb_fn_name(type), type, type));
871 reply_doserror(req, ERRSRV, ERRunknownsmb);
875 /****************************************************************************
877 conn POINTER CAN BE NULL HERE !
878 ****************************************************************************/
880 void reply_ioctl(struct smb_request *req)
882 connection_struct *conn = req->conn;
889 START_PROFILE(SMBioctl);
892 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
893 END_PROFILE(SMBioctl);
897 device = SVAL(req->vwv+1, 0);
898 function = SVAL(req->vwv+2, 0);
899 ioctl_code = (device << 16) + function;
901 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
903 switch (ioctl_code) {
904 case IOCTL_QUERY_JOB_INFO:
908 reply_doserror(req, ERRSRV, ERRnosupport);
909 END_PROFILE(SMBioctl);
913 reply_outbuf(req, 8, replysize+1);
914 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
915 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
916 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
917 p = smb_buf(req->outbuf);
918 memset(p, '\0', replysize+1); /* valgrind-safe. */
919 p += 1; /* Allow for alignment */
921 switch (ioctl_code) {
922 case IOCTL_QUERY_JOB_INFO:
924 files_struct *fsp = file_fsp(
925 req, SVAL(req->vwv+0, 0));
927 reply_doserror(req, ERRDOS, ERRbadfid);
928 END_PROFILE(SMBioctl);
931 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
932 srvstr_push((char *)req->outbuf, req->flags2, p+2,
934 STR_TERMINATE|STR_ASCII);
936 srvstr_push((char *)req->outbuf, req->flags2,
937 p+18, lp_servicename(SNUM(conn)),
938 13, STR_TERMINATE|STR_ASCII);
946 END_PROFILE(SMBioctl);
950 /****************************************************************************
951 Strange checkpath NTSTATUS mapping.
952 ****************************************************************************/
954 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
956 /* Strange DOS error code semantics only for checkpath... */
957 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
958 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
959 /* We need to map to ERRbadpath */
960 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
966 /****************************************************************************
967 Reply to a checkpath.
968 ****************************************************************************/
970 void reply_checkpath(struct smb_request *req)
972 connection_struct *conn = req->conn;
973 struct smb_filename *smb_fname = NULL;
976 TALLOC_CTX *ctx = talloc_tos();
978 START_PROFILE(SMBcheckpath);
980 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
981 STR_TERMINATE, &status);
983 if (!NT_STATUS_IS_OK(status)) {
984 status = map_checkpath_error(req->flags2, status);
985 reply_nterror(req, status);
986 END_PROFILE(SMBcheckpath);
990 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
992 status = filename_convert(ctx,
994 req->flags2 & FLAGS2_DFS_PATHNAMES,
999 if (!NT_STATUS_IS_OK(status)) {
1000 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1001 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1002 ERRSRV, ERRbadpath);
1003 END_PROFILE(SMBcheckpath);
1009 if (!VALID_STAT(smb_fname->st) &&
1010 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1011 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1012 smb_fname_str_dbg(smb_fname), strerror(errno)));
1013 status = map_nt_error_from_unix(errno);
1017 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1018 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1019 ERRDOS, ERRbadpath);
1023 reply_outbuf(req, 0, 0);
1026 /* We special case this - as when a Windows machine
1027 is parsing a path is steps through the components
1028 one at a time - if a component fails it expects
1029 ERRbadpath, not ERRbadfile.
1031 status = map_checkpath_error(req->flags2, status);
1032 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1034 * Windows returns different error codes if
1035 * the parent directory is valid but not the
1036 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1037 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1038 * if the path is invalid.
1040 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1041 ERRDOS, ERRbadpath);
1045 reply_nterror(req, status);
1048 TALLOC_FREE(smb_fname);
1049 END_PROFILE(SMBcheckpath);
1053 /****************************************************************************
1055 ****************************************************************************/
1057 void reply_getatr(struct smb_request *req)
1059 connection_struct *conn = req->conn;
1060 struct smb_filename *smb_fname = NULL;
1067 TALLOC_CTX *ctx = talloc_tos();
1069 START_PROFILE(SMBgetatr);
1071 p = (const char *)req->buf + 1;
1072 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1073 if (!NT_STATUS_IS_OK(status)) {
1074 reply_nterror(req, status);
1078 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1079 under WfWg - weird! */
1080 if (*fname == '\0') {
1081 mode = aHIDDEN | aDIR;
1082 if (!CAN_WRITE(conn)) {
1088 status = filename_convert(ctx,
1090 req->flags2 & FLAGS2_DFS_PATHNAMES,
1094 if (!NT_STATUS_IS_OK(status)) {
1095 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1096 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1097 ERRSRV, ERRbadpath);
1100 reply_nterror(req, status);
1103 if (!VALID_STAT(smb_fname->st) &&
1104 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1105 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1106 smb_fname_str_dbg(smb_fname),
1108 reply_unixerror(req, ERRDOS,ERRbadfile);
1112 mode = dos_mode(conn, fname, &smb_fname->st);
1113 size = smb_fname->st.st_ex_size;
1114 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1120 reply_outbuf(req, 10, 0);
1122 SSVAL(req->outbuf,smb_vwv0,mode);
1123 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1124 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1126 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1128 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1130 if (Protocol >= PROTOCOL_NT1) {
1131 SSVAL(req->outbuf, smb_flg2,
1132 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1135 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1136 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1139 TALLOC_FREE(smb_fname);
1141 END_PROFILE(SMBgetatr);
1145 /****************************************************************************
1147 ****************************************************************************/
1149 void reply_setatr(struct smb_request *req)
1151 struct smb_file_time ft;
1152 connection_struct *conn = req->conn;
1153 struct smb_filename *smb_fname = NULL;
1159 TALLOC_CTX *ctx = talloc_tos();
1161 START_PROFILE(SMBsetatr);
1166 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1170 p = (const char *)req->buf + 1;
1171 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1172 if (!NT_STATUS_IS_OK(status)) {
1173 reply_nterror(req, status);
1177 status = filename_convert(ctx,
1179 req->flags2 & FLAGS2_DFS_PATHNAMES,
1183 if (!NT_STATUS_IS_OK(status)) {
1184 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1185 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1186 ERRSRV, ERRbadpath);
1189 reply_nterror(req, status);
1193 if (fname[0] == '.' && fname[1] == '\0') {
1195 * Not sure here is the right place to catch this
1196 * condition. Might be moved to somewhere else later -- vl
1198 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1202 mode = SVAL(req->vwv+0, 0);
1203 mtime = srv_make_unix_date3(req->vwv+1);
1205 ft.mtime = convert_time_t_to_timespec(mtime);
1206 status = smb_set_file_time(conn, NULL, fname,
1207 &smb_fname->st, &ft, true);
1208 if (!NT_STATUS_IS_OK(status)) {
1209 reply_unixerror(req, ERRDOS, ERRnoaccess);
1213 if (mode != FILE_ATTRIBUTE_NORMAL) {
1214 if (VALID_STAT_OF_DIR(smb_fname->st))
1219 if (file_set_dosmode(conn, 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", fname, mode ) );
1230 TALLOC_FREE(smb_fname);
1231 END_PROFILE(SMBsetatr);
1235 /****************************************************************************
1237 ****************************************************************************/
1239 void reply_dskattr(struct smb_request *req)
1241 connection_struct *conn = req->conn;
1242 uint64_t dfree,dsize,bsize;
1243 START_PROFILE(SMBdskattr);
1245 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1246 reply_unixerror(req, ERRHRD, ERRgeneral);
1247 END_PROFILE(SMBdskattr);
1251 reply_outbuf(req, 5, 0);
1253 if (Protocol <= PROTOCOL_LANMAN2) {
1254 double total_space, free_space;
1255 /* we need to scale this to a number that DOS6 can handle. We
1256 use floating point so we can handle large drives on systems
1257 that don't have 64 bit integers
1259 we end up displaying a maximum of 2G to DOS systems
1261 total_space = dsize * (double)bsize;
1262 free_space = dfree * (double)bsize;
1264 dsize = (uint64_t)((total_space+63*512) / (64*512));
1265 dfree = (uint64_t)((free_space+63*512) / (64*512));
1267 if (dsize > 0xFFFF) dsize = 0xFFFF;
1268 if (dfree > 0xFFFF) dfree = 0xFFFF;
1270 SSVAL(req->outbuf,smb_vwv0,dsize);
1271 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1272 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1273 SSVAL(req->outbuf,smb_vwv3,dfree);
1275 SSVAL(req->outbuf,smb_vwv0,dsize);
1276 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1277 SSVAL(req->outbuf,smb_vwv2,512);
1278 SSVAL(req->outbuf,smb_vwv3,dfree);
1281 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1283 END_PROFILE(SMBdskattr);
1288 * Utility function to split the filename from the directory.
1290 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1291 char **fname_dir_out,
1292 char **fname_mask_out)
1294 const char *p = NULL;
1295 char *fname_dir = NULL;
1296 char *fname_mask = NULL;
1298 p = strrchr_m(fname_in, '/');
1300 fname_dir = talloc_strdup(ctx, ".");
1301 fname_mask = talloc_strdup(ctx, fname_in);
1303 fname_dir = talloc_strndup(ctx, fname_in,
1304 PTR_DIFF(p, fname_in));
1305 fname_mask = talloc_strdup(ctx, p+1);
1308 if (!fname_dir || !fname_mask) {
1309 TALLOC_FREE(fname_dir);
1310 TALLOC_FREE(fname_mask);
1311 return NT_STATUS_NO_MEMORY;
1314 *fname_dir_out = fname_dir;
1315 *fname_mask_out = fname_mask;
1316 return NT_STATUS_OK;
1319 /****************************************************************************
1321 Can be called from SMBsearch, SMBffirst or SMBfunique.
1322 ****************************************************************************/
1324 void reply_search(struct smb_request *req)
1326 connection_struct *conn = req->conn;
1328 const char *mask = NULL;
1329 char *directory = NULL;
1333 struct timespec date;
1335 unsigned int numentries = 0;
1336 unsigned int maxentries = 0;
1337 bool finished = False;
1342 bool check_descend = False;
1343 bool expect_close = False;
1345 bool mask_contains_wcard = False;
1346 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1347 TALLOC_CTX *ctx = talloc_tos();
1348 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1350 START_PROFILE(SMBsearch);
1353 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1354 END_PROFILE(SMBsearch);
1358 if (lp_posix_pathnames()) {
1359 reply_unknown_new(req, req->cmd);
1360 END_PROFILE(SMBsearch);
1364 /* If we were called as SMBffirst then we must expect close. */
1365 if(req->cmd == SMBffirst) {
1366 expect_close = True;
1369 reply_outbuf(req, 1, 3);
1370 maxentries = SVAL(req->vwv+0, 0);
1371 dirtype = SVAL(req->vwv+1, 0);
1372 p = (const char *)req->buf + 1;
1373 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1374 &nt_status, &mask_contains_wcard);
1375 if (!NT_STATUS_IS_OK(nt_status)) {
1376 reply_nterror(req, nt_status);
1377 END_PROFILE(SMBsearch);
1382 status_len = SVAL(p, 0);
1385 /* dirtype &= ~aDIR; */
1387 if (status_len == 0) {
1388 struct smb_filename *smb_fname = NULL;
1390 nt_status = resolve_dfspath_wcard(ctx, conn,
1391 req->flags2 & FLAGS2_DFS_PATHNAMES,
1394 &mask_contains_wcard);
1395 if (!NT_STATUS_IS_OK(nt_status)) {
1396 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1397 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1398 ERRSRV, ERRbadpath);
1399 END_PROFILE(SMBsearch);
1402 reply_nterror(req, nt_status);
1403 END_PROFILE(SMBsearch);
1407 nt_status = unix_convert(ctx, conn, path, &smb_fname,
1408 UCF_ALLOW_WCARD_LCOMP);
1409 if (!NT_STATUS_IS_OK(nt_status)) {
1410 reply_nterror(req, nt_status);
1411 END_PROFILE(SMBsearch);
1415 nt_status = get_full_smb_filename(ctx, smb_fname, &directory);
1416 TALLOC_FREE(smb_fname);
1417 if (!NT_STATUS_IS_OK(nt_status)) {
1418 reply_nterror(req, nt_status);
1419 END_PROFILE(SMBsearch);
1423 nt_status = check_name(conn, directory);
1424 if (!NT_STATUS_IS_OK(nt_status)) {
1425 reply_nterror(req, nt_status);
1426 END_PROFILE(SMBsearch);
1430 p = strrchr_m(directory,'/');
1431 if ((p != NULL) && (*directory != '/')) {
1433 directory = talloc_strndup(ctx, directory,
1434 PTR_DIFF(p, directory));
1437 directory = talloc_strdup(ctx,".");
1441 reply_nterror(req, NT_STATUS_NO_MEMORY);
1442 END_PROFILE(SMBsearch);
1446 memset((char *)status,'\0',21);
1447 SCVAL(status,0,(dirtype & 0x1F));
1449 nt_status = dptr_create(conn,
1455 mask_contains_wcard,
1458 if (!NT_STATUS_IS_OK(nt_status)) {
1459 reply_nterror(req, nt_status);
1460 END_PROFILE(SMBsearch);
1463 dptr_num = dptr_dnum(conn->dirptr);
1467 memcpy(status,p,21);
1468 status_dirtype = CVAL(status,0) & 0x1F;
1469 if (status_dirtype != (dirtype & 0x1F)) {
1470 dirtype = status_dirtype;
1473 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1474 if (!conn->dirptr) {
1477 string_set(&conn->dirpath,dptr_path(dptr_num));
1478 mask = dptr_wcard(dptr_num);
1483 * For a 'continue' search we have no string. So
1484 * check from the initial saved string.
1486 mask_contains_wcard = ms_has_wild(mask);
1487 dirtype = dptr_attr(dptr_num);
1490 DEBUG(4,("dptr_num is %d\n",dptr_num));
1492 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1493 dptr_init_search_op(conn->dirptr);
1495 if ((dirtype&0x1F) == aVOLID) {
1496 char buf[DIR_STRUCT_SIZE];
1497 memcpy(buf,status,21);
1498 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1499 0,aVOLID,0,!allow_long_path_components)) {
1500 reply_nterror(req, NT_STATUS_NO_MEMORY);
1501 END_PROFILE(SMBsearch);
1504 dptr_fill(buf+12,dptr_num);
1505 if (dptr_zero(buf+12) && (status_len==0)) {
1510 if (message_push_blob(&req->outbuf,
1511 data_blob_const(buf, sizeof(buf)))
1513 reply_nterror(req, NT_STATUS_NO_MEMORY);
1514 END_PROFILE(SMBsearch);
1522 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1525 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1526 conn->dirpath,lp_dontdescend(SNUM(conn))));
1527 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1528 check_descend = True;
1531 for (i=numentries;(i<maxentries) && !finished;i++) {
1532 finished = !get_dir_entry(ctx,
1543 char buf[DIR_STRUCT_SIZE];
1544 memcpy(buf,status,21);
1545 if (!make_dir_struct(ctx,
1551 convert_timespec_to_time_t(date),
1552 !allow_long_path_components)) {
1553 reply_nterror(req, NT_STATUS_NO_MEMORY);
1554 END_PROFILE(SMBsearch);
1557 if (!dptr_fill(buf+12,dptr_num)) {
1560 if (message_push_blob(&req->outbuf,
1561 data_blob_const(buf, sizeof(buf)))
1563 reply_nterror(req, NT_STATUS_NO_MEMORY);
1564 END_PROFILE(SMBsearch);
1574 /* If we were called as SMBffirst with smb_search_id == NULL
1575 and no entries were found then return error and close dirptr
1578 if (numentries == 0) {
1579 dptr_close(&dptr_num);
1580 } else if(expect_close && status_len == 0) {
1581 /* Close the dptr - we know it's gone */
1582 dptr_close(&dptr_num);
1585 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1586 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1587 dptr_close(&dptr_num);
1590 if ((numentries == 0) && !mask_contains_wcard) {
1591 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1592 END_PROFILE(SMBsearch);
1596 SSVAL(req->outbuf,smb_vwv0,numentries);
1597 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1598 SCVAL(smb_buf(req->outbuf),0,5);
1599 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1601 /* The replies here are never long name. */
1602 SSVAL(req->outbuf, smb_flg2,
1603 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1604 if (!allow_long_path_components) {
1605 SSVAL(req->outbuf, smb_flg2,
1606 SVAL(req->outbuf, smb_flg2)
1607 & (~FLAGS2_LONG_PATH_COMPONENTS));
1610 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1611 SSVAL(req->outbuf, smb_flg2,
1612 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1615 directory = dptr_path(dptr_num);
1618 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1619 smb_fn_name(req->cmd),
1621 directory ? directory : "./",
1626 END_PROFILE(SMBsearch);
1630 /****************************************************************************
1631 Reply to a fclose (stop directory search).
1632 ****************************************************************************/
1634 void reply_fclose(struct smb_request *req)
1642 bool path_contains_wcard = False;
1643 TALLOC_CTX *ctx = talloc_tos();
1645 START_PROFILE(SMBfclose);
1647 if (lp_posix_pathnames()) {
1648 reply_unknown_new(req, req->cmd);
1649 END_PROFILE(SMBfclose);
1653 p = (const char *)req->buf + 1;
1654 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1655 &err, &path_contains_wcard);
1656 if (!NT_STATUS_IS_OK(err)) {
1657 reply_nterror(req, err);
1658 END_PROFILE(SMBfclose);
1662 status_len = SVAL(p,0);
1665 if (status_len == 0) {
1666 reply_doserror(req, ERRSRV, ERRsrverror);
1667 END_PROFILE(SMBfclose);
1671 memcpy(status,p,21);
1673 if(dptr_fetch(status+12,&dptr_num)) {
1674 /* Close the dptr - we know it's gone */
1675 dptr_close(&dptr_num);
1678 reply_outbuf(req, 1, 0);
1679 SSVAL(req->outbuf,smb_vwv0,0);
1681 DEBUG(3,("search close\n"));
1683 END_PROFILE(SMBfclose);
1687 /****************************************************************************
1689 ****************************************************************************/
1691 void reply_open(struct smb_request *req)
1693 connection_struct *conn = req->conn;
1694 struct smb_filename *smb_fname = NULL;
1706 uint32 create_disposition;
1707 uint32 create_options = 0;
1709 TALLOC_CTX *ctx = talloc_tos();
1711 START_PROFILE(SMBopen);
1714 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1718 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1719 deny_mode = SVAL(req->vwv+0, 0);
1720 dos_attr = SVAL(req->vwv+1, 0);
1722 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1723 STR_TERMINATE, &status);
1724 if (!NT_STATUS_IS_OK(status)) {
1725 reply_nterror(req, status);
1729 status = filename_convert(ctx,
1731 req->flags2 & FLAGS2_DFS_PATHNAMES,
1735 if (!NT_STATUS_IS_OK(status)) {
1736 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1737 reply_botherror(req,
1738 NT_STATUS_PATH_NOT_COVERED,
1739 ERRSRV, ERRbadpath);
1742 reply_nterror(req, status);
1746 if (!map_open_params_to_ntcreate(
1747 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1748 &share_mode, &create_disposition, &create_options)) {
1749 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1753 status = SMB_VFS_CREATE_FILE(
1756 0, /* root_dir_fid */
1757 smb_fname, /* fname */
1758 access_mask, /* access_mask */
1759 share_mode, /* share_access */
1760 create_disposition, /* create_disposition*/
1761 create_options, /* create_options */
1762 dos_attr, /* file_attributes */
1763 oplock_request, /* oplock_request */
1764 0, /* allocation_size */
1770 if (!NT_STATUS_IS_OK(status)) {
1771 if (open_was_deferred(req->mid)) {
1772 /* We have re-scheduled this call. */
1775 reply_openerror(req, status);
1779 size = smb_fname->st.st_ex_size;
1780 fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st);
1781 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1784 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1785 close_file(req, fsp, ERROR_CLOSE);
1786 reply_doserror(req, ERRDOS,ERRnoaccess);
1790 reply_outbuf(req, 7, 0);
1791 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1792 SSVAL(req->outbuf,smb_vwv1,fattr);
1793 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1794 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1796 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1798 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1799 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1801 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1802 SCVAL(req->outbuf,smb_flg,
1803 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1806 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1807 SCVAL(req->outbuf,smb_flg,
1808 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1811 TALLOC_FREE(smb_fname);
1812 END_PROFILE(SMBopen);
1816 /****************************************************************************
1817 Reply to an open and X.
1818 ****************************************************************************/
1820 void reply_open_and_X(struct smb_request *req)
1822 connection_struct *conn = req->conn;
1823 struct smb_filename *smb_fname = NULL;
1828 /* Breakout the oplock request bits so we can set the
1829 reply bits separately. */
1830 int ex_oplock_request;
1831 int core_oplock_request;
1834 int smb_sattr = SVAL(req->vwv+4, 0);
1835 uint32 smb_time = make_unix_date3(req->vwv+6);
1843 uint64_t allocation_size;
1844 ssize_t retval = -1;
1847 uint32 create_disposition;
1848 uint32 create_options = 0;
1849 TALLOC_CTX *ctx = talloc_tos();
1851 START_PROFILE(SMBopenX);
1853 if (req->wct < 15) {
1854 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1858 open_flags = SVAL(req->vwv+2, 0);
1859 deny_mode = SVAL(req->vwv+3, 0);
1860 smb_attr = SVAL(req->vwv+5, 0);
1861 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1862 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1863 oplock_request = ex_oplock_request | core_oplock_request;
1864 smb_ofun = SVAL(req->vwv+8, 0);
1865 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1867 /* If it's an IPC, pass off the pipe handler. */
1869 if (lp_nt_pipe_support()) {
1870 reply_open_pipe_and_X(conn, req);
1872 reply_doserror(req, ERRSRV, ERRaccess);
1877 /* XXXX we need to handle passed times, sattr and flags */
1878 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1879 STR_TERMINATE, &status);
1880 if (!NT_STATUS_IS_OK(status)) {
1881 reply_nterror(req, status);
1885 status = filename_convert(ctx,
1887 req->flags2 & FLAGS2_DFS_PATHNAMES,
1891 if (!NT_STATUS_IS_OK(status)) {
1892 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1893 reply_botherror(req,
1894 NT_STATUS_PATH_NOT_COVERED,
1895 ERRSRV, ERRbadpath);
1898 reply_nterror(req, status);
1902 if (!map_open_params_to_ntcreate(
1903 fname, deny_mode, smb_ofun, &access_mask,
1904 &share_mode, &create_disposition, &create_options)) {
1905 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1909 status = SMB_VFS_CREATE_FILE(
1912 0, /* root_dir_fid */
1913 smb_fname, /* fname */
1914 access_mask, /* access_mask */
1915 share_mode, /* share_access */
1916 create_disposition, /* create_disposition*/
1917 create_options, /* create_options */
1918 smb_attr, /* file_attributes */
1919 oplock_request, /* oplock_request */
1920 0, /* allocation_size */
1924 &smb_action); /* pinfo */
1926 if (!NT_STATUS_IS_OK(status)) {
1927 if (open_was_deferred(req->mid)) {
1928 /* We have re-scheduled this call. */
1931 reply_openerror(req, status);
1935 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1936 if the file is truncated or created. */
1937 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1938 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1939 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1940 close_file(req, fsp, ERROR_CLOSE);
1941 reply_nterror(req, NT_STATUS_DISK_FULL);
1944 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1946 close_file(req, fsp, ERROR_CLOSE);
1947 reply_nterror(req, NT_STATUS_DISK_FULL);
1950 smb_fname->st.st_ex_size =
1951 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1954 fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st);
1955 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1957 close_file(req, fsp, ERROR_CLOSE);
1958 reply_doserror(req, ERRDOS, ERRnoaccess);
1962 /* If the caller set the extended oplock request bit
1963 and we granted one (by whatever means) - set the
1964 correct bit for extended oplock reply.
1967 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1968 smb_action |= EXTENDED_OPLOCK_GRANTED;
1971 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1972 smb_action |= EXTENDED_OPLOCK_GRANTED;
1975 /* If the caller set the core oplock request bit
1976 and we granted one (by whatever means) - set the
1977 correct bit for core oplock reply.
1980 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1981 reply_outbuf(req, 19, 0);
1983 reply_outbuf(req, 15, 0);
1986 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1987 SCVAL(req->outbuf, smb_flg,
1988 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1991 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1992 SCVAL(req->outbuf, smb_flg,
1993 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1996 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1997 SSVAL(req->outbuf,smb_vwv3,fattr);
1998 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1999 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2001 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2003 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2004 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2005 SSVAL(req->outbuf,smb_vwv11,smb_action);
2007 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2008 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2013 TALLOC_FREE(smb_fname);
2014 END_PROFILE(SMBopenX);
2018 /****************************************************************************
2019 Reply to a SMBulogoffX.
2020 ****************************************************************************/
2022 void reply_ulogoffX(struct smb_request *req)
2024 struct smbd_server_connection *sconn = smbd_server_conn;
2027 START_PROFILE(SMBulogoffX);
2029 vuser = get_valid_user_struct(sconn, req->vuid);
2032 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2036 /* in user level security we are supposed to close any files
2037 open by this user */
2038 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2039 file_close_user(req->vuid);
2042 invalidate_vuid(sconn, req->vuid);
2044 reply_outbuf(req, 2, 0);
2046 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2048 END_PROFILE(SMBulogoffX);
2052 /****************************************************************************
2053 Reply to a mknew or a create.
2054 ****************************************************************************/
2056 void reply_mknew(struct smb_request *req)
2058 connection_struct *conn = req->conn;
2059 struct smb_filename *smb_fname = NULL;
2062 struct smb_file_time ft;
2064 int oplock_request = 0;
2066 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2067 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2068 uint32 create_disposition;
2069 uint32 create_options = 0;
2070 TALLOC_CTX *ctx = talloc_tos();
2072 START_PROFILE(SMBcreate);
2076 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2080 fattr = SVAL(req->vwv+0, 0);
2081 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2084 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2086 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2087 STR_TERMINATE, &status);
2088 if (!NT_STATUS_IS_OK(status)) {
2089 reply_nterror(req, status);
2093 status = filename_convert(ctx,
2095 req->flags2 & FLAGS2_DFS_PATHNAMES,
2099 if (!NT_STATUS_IS_OK(status)) {
2100 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2101 reply_botherror(req,
2102 NT_STATUS_PATH_NOT_COVERED,
2103 ERRSRV, ERRbadpath);
2106 reply_nterror(req, status);
2110 if (fattr & aVOLID) {
2111 DEBUG(0,("Attempt to create file (%s) with volid set - "
2112 "please report this\n",
2113 smb_fname_str_dbg(smb_fname)));
2116 if(req->cmd == SMBmknew) {
2117 /* We should fail if file exists. */
2118 create_disposition = FILE_CREATE;
2120 /* Create if file doesn't exist, truncate if it does. */
2121 create_disposition = FILE_OVERWRITE_IF;
2124 status = SMB_VFS_CREATE_FILE(
2127 0, /* root_dir_fid */
2128 smb_fname, /* fname */
2129 access_mask, /* access_mask */
2130 share_mode, /* share_access */
2131 create_disposition, /* create_disposition*/
2132 create_options, /* create_options */
2133 fattr, /* file_attributes */
2134 oplock_request, /* oplock_request */
2135 0, /* allocation_size */
2141 if (!NT_STATUS_IS_OK(status)) {
2142 if (open_was_deferred(req->mid)) {
2143 /* We have re-scheduled this call. */
2146 reply_openerror(req, status);
2150 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2151 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &smb_fname->st,
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", fsp->fsp_name ) );
2172 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2173 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2176 TALLOC_FREE(smb_fname);
2177 END_PROFILE(SMBcreate);
2181 /****************************************************************************
2182 Reply to a create temporary file.
2183 ****************************************************************************/
2185 void reply_ctemp(struct smb_request *req)
2187 connection_struct *conn = req->conn;
2188 struct smb_filename *smb_fname = NULL;
2196 TALLOC_CTX *ctx = talloc_tos();
2198 START_PROFILE(SMBctemp);
2201 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2205 fattr = SVAL(req->vwv+0, 0);
2206 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2208 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2209 STR_TERMINATE, &status);
2210 if (!NT_STATUS_IS_OK(status)) {
2211 reply_nterror(req, status);
2215 fname = talloc_asprintf(ctx,
2219 fname = talloc_strdup(ctx, "TMXXXXXX");
2223 reply_nterror(req, NT_STATUS_NO_MEMORY);
2227 status = filename_convert(ctx, conn,
2228 req->flags2 & FLAGS2_DFS_PATHNAMES,
2232 if (!NT_STATUS_IS_OK(status)) {
2233 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2234 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2235 ERRSRV, ERRbadpath);
2238 reply_nterror(req, status);
2242 tmpfd = mkstemp(smb_fname->base_name);
2244 reply_unixerror(req, ERRDOS, ERRnoaccess);
2248 SMB_VFS_STAT(conn, smb_fname);
2250 /* We should fail if file does not exist. */
2251 status = SMB_VFS_CREATE_FILE(
2254 0, /* root_dir_fid */
2255 smb_fname, /* fname */
2256 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2257 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2258 FILE_OPEN, /* create_disposition*/
2259 0, /* create_options */
2260 fattr, /* file_attributes */
2261 oplock_request, /* oplock_request */
2262 0, /* allocation_size */
2268 /* close fd from mkstemp() */
2271 if (!NT_STATUS_IS_OK(status)) {
2272 if (open_was_deferred(req->mid)) {
2273 /* We have re-scheduled this call. */
2276 reply_openerror(req, status);
2280 reply_outbuf(req, 1, 0);
2281 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2283 /* the returned filename is relative to the directory */
2284 s = strrchr_m(fsp->fsp_name, '/');
2292 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2293 thing in the byte section. JRA */
2294 SSVALS(p, 0, -1); /* what is this? not in spec */
2296 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2298 reply_nterror(req, NT_STATUS_NO_MEMORY);
2302 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2303 SCVAL(req->outbuf, smb_flg,
2304 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2307 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2308 SCVAL(req->outbuf, smb_flg,
2309 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2312 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2313 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2314 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2316 TALLOC_FREE(smb_fname);
2317 END_PROFILE(SMBctemp);
2321 /*******************************************************************
2322 Check if a user is allowed to rename a file.
2323 ********************************************************************/
2325 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2326 uint16 dirtype, SMB_STRUCT_STAT *pst)
2330 if (!CAN_WRITE(conn)) {
2331 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2334 fmode = dos_mode(conn, fsp->fsp_name, pst);
2335 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2336 return NT_STATUS_NO_SUCH_FILE;
2339 if (S_ISDIR(pst->st_ex_mode)) {
2340 if (fsp->posix_open) {
2341 return NT_STATUS_OK;
2344 /* If no pathnames are open below this
2345 directory, allow the rename. */
2347 if (file_find_subpath(fsp)) {
2348 return NT_STATUS_ACCESS_DENIED;
2350 return NT_STATUS_OK;
2353 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2354 return NT_STATUS_OK;
2357 return NT_STATUS_ACCESS_DENIED;
2360 /*******************************************************************
2361 * unlink a file with all relevant access checks
2362 *******************************************************************/
2364 static NTSTATUS do_unlink(connection_struct *conn,
2365 struct smb_request *req,
2366 struct smb_filename *smb_fname,
2372 uint32 dirtype_orig = dirtype;
2375 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2377 if (!CAN_WRITE(conn)) {
2378 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2381 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
2382 return map_nt_error_from_unix(errno);
2385 status = get_full_smb_filename(smb_fname, smb_fname, &fname);
2386 if (!NT_STATUS_IS_OK(status)) {
2389 fattr = dos_mode(conn, fname, &smb_fname->st);
2392 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2393 dirtype = aDIR|aARCH|aRONLY;
2396 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2398 return NT_STATUS_NO_SUCH_FILE;
2401 if (!dir_check_ftype(conn, fattr, dirtype)) {
2403 return NT_STATUS_FILE_IS_A_DIRECTORY;
2405 return NT_STATUS_NO_SUCH_FILE;
2408 if (dirtype_orig & 0x8000) {
2409 /* These will never be set for POSIX. */
2410 return NT_STATUS_NO_SUCH_FILE;
2414 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2415 return NT_STATUS_FILE_IS_A_DIRECTORY;
2418 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2419 return NT_STATUS_NO_SUCH_FILE;
2422 if (dirtype & 0xFF00) {
2423 /* These will never be set for POSIX. */
2424 return NT_STATUS_NO_SUCH_FILE;
2429 return NT_STATUS_NO_SUCH_FILE;
2432 /* Can't delete a directory. */
2434 return NT_STATUS_FILE_IS_A_DIRECTORY;
2439 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2440 return NT_STATUS_OBJECT_NAME_INVALID;
2441 #endif /* JRATEST */
2443 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2445 On a Windows share, a file with read-only dosmode can be opened with
2446 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2447 fails with NT_STATUS_CANNOT_DELETE error.
2449 This semantic causes a problem that a user can not
2450 rename a file with read-only dosmode on a Samba share
2451 from a Windows command prompt (i.e. cmd.exe, but can rename
2452 from Windows Explorer).
2455 if (!lp_delete_readonly(SNUM(conn))) {
2456 if (fattr & aRONLY) {
2457 return NT_STATUS_CANNOT_DELETE;
2461 /* On open checks the open itself will check the share mode, so
2462 don't do it here as we'll get it wrong. */
2464 status = SMB_VFS_CREATE_FILE
2467 0, /* root_dir_fid */
2468 smb_fname, /* fname */
2469 DELETE_ACCESS, /* access_mask */
2470 FILE_SHARE_NONE, /* share_access */
2471 FILE_OPEN, /* create_disposition*/
2472 FILE_NON_DIRECTORY_FILE, /* create_options */
2473 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2474 0, /* oplock_request */
2475 0, /* allocation_size */
2481 if (!NT_STATUS_IS_OK(status)) {
2482 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2483 nt_errstr(status)));
2487 /* The set is across all open files on this dev/inode pair. */
2488 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2489 close_file(req, fsp, NORMAL_CLOSE);
2490 return NT_STATUS_ACCESS_DENIED;
2493 return close_file(req, fsp, NORMAL_CLOSE);
2496 /****************************************************************************
2497 The guts of the unlink command, split out so it may be called by the NT SMB
2499 ****************************************************************************/
2501 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2502 uint32 dirtype, const char *name_in, bool has_wild)
2504 struct smb_filename *smb_fname = NULL;
2505 char *fname_dir = NULL;
2506 char *fname_mask = NULL;
2508 NTSTATUS status = NT_STATUS_OK;
2509 TALLOC_CTX *ctx = talloc_tos();
2511 status = unix_convert(ctx, conn, name_in, &smb_fname,
2512 has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
2513 if (!NT_STATUS_IS_OK(status)) {
2517 /* Split up the directory from the filename/mask. */
2518 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2519 &fname_dir, &fname_mask);
2520 if (!NT_STATUS_IS_OK(status)) {
2525 * We should only check the mangled cache
2526 * here if unix_convert failed. This means
2527 * that the path in 'mask' doesn't exist
2528 * on the file system and so we need to look
2529 * for a possible mangle. This patch from
2530 * Tine Smukavec <valentin.smukavec@hermes.si>.
2533 if (!VALID_STAT(smb_fname->st) &&
2534 mangle_is_mangled(fname_mask, conn->params)) {
2535 char *new_mask = NULL;
2536 mangle_lookup_name_from_8_3(ctx, fname_mask,
2537 &new_mask, conn->params);
2539 TALLOC_FREE(fname_mask);
2540 fname_mask = new_mask;
2547 * Only one file needs to be unlinked. Append the mask back
2548 * onto the directory.
2550 TALLOC_FREE(smb_fname->base_name);
2551 smb_fname->base_name = talloc_asprintf(smb_fname,
2555 if (!smb_fname->base_name) {
2556 status = NT_STATUS_NO_MEMORY;
2560 dirtype = FILE_ATTRIBUTE_NORMAL;
2563 status = check_name(conn, smb_fname->base_name);
2564 if (!NT_STATUS_IS_OK(status)) {
2568 status = do_unlink(conn, req, smb_fname, dirtype);
2569 if (!NT_STATUS_IS_OK(status)) {
2575 struct smb_Dir *dir_hnd = NULL;
2579 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2580 status = NT_STATUS_OBJECT_NAME_INVALID;
2584 if (strequal(fname_mask,"????????.???")) {
2585 TALLOC_FREE(fname_mask);
2586 fname_mask = talloc_strdup(ctx, "*");
2588 status = NT_STATUS_NO_MEMORY;
2593 status = check_name(conn, fname_dir);
2594 if (!NT_STATUS_IS_OK(status)) {
2598 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2600 if (dir_hnd == NULL) {
2601 status = map_nt_error_from_unix(errno);
2605 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2606 the pattern matches against the long name, otherwise the short name
2607 We don't implement this yet XXXX
2610 status = NT_STATUS_NO_SUCH_FILE;
2612 while ((dname = ReadDirName(dir_hnd, &offset,
2614 if (!is_visible_file(conn, fname_dir, dname,
2615 &smb_fname->st, true)) {
2619 /* Quick check for "." and ".." */
2620 if (ISDOT(dname) || ISDOTDOT(dname)) {
2624 if(!mask_match(dname, fname_mask,
2625 conn->case_sensitive)) {
2629 TALLOC_FREE(smb_fname->base_name);
2630 smb_fname->base_name =
2631 talloc_asprintf(smb_fname, "%s/%s",
2634 if (!smb_fname->base_name) {
2635 TALLOC_FREE(dir_hnd);
2636 status = NT_STATUS_NO_MEMORY;
2640 status = check_name(conn, smb_fname->base_name);
2641 if (!NT_STATUS_IS_OK(status)) {
2642 TALLOC_FREE(dir_hnd);
2646 status = do_unlink(conn, req, smb_fname, dirtype);
2647 if (!NT_STATUS_IS_OK(status)) {
2652 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2653 smb_fname->base_name));
2655 TALLOC_FREE(dir_hnd);
2658 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2659 status = map_nt_error_from_unix(errno);
2663 TALLOC_FREE(smb_fname);
2664 TALLOC_FREE(fname_dir);
2665 TALLOC_FREE(fname_mask);
2669 /****************************************************************************
2671 ****************************************************************************/
2673 void reply_unlink(struct smb_request *req)
2675 connection_struct *conn = req->conn;
2679 bool path_contains_wcard = False;
2680 TALLOC_CTX *ctx = talloc_tos();
2682 START_PROFILE(SMBunlink);
2685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2686 END_PROFILE(SMBunlink);
2690 dirtype = SVAL(req->vwv+0, 0);
2692 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2693 STR_TERMINATE, &status,
2694 &path_contains_wcard);
2695 if (!NT_STATUS_IS_OK(status)) {
2696 reply_nterror(req, status);
2697 END_PROFILE(SMBunlink);
2701 status = resolve_dfspath_wcard(ctx, conn,
2702 req->flags2 & FLAGS2_DFS_PATHNAMES,
2705 &path_contains_wcard);
2706 if (!NT_STATUS_IS_OK(status)) {
2707 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2708 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2709 ERRSRV, ERRbadpath);
2710 END_PROFILE(SMBunlink);
2713 reply_nterror(req, status);
2714 END_PROFILE(SMBunlink);
2718 DEBUG(3,("reply_unlink : %s\n",name));
2720 status = unlink_internals(conn, req, dirtype, name,
2721 path_contains_wcard);
2722 if (!NT_STATUS_IS_OK(status)) {
2723 if (open_was_deferred(req->mid)) {
2724 /* We have re-scheduled this call. */
2725 END_PROFILE(SMBunlink);
2728 reply_nterror(req, status);
2729 END_PROFILE(SMBunlink);
2733 reply_outbuf(req, 0, 0);
2734 END_PROFILE(SMBunlink);
2739 /****************************************************************************
2741 ****************************************************************************/
2743 static void fail_readraw(void)
2745 const char *errstr = talloc_asprintf(talloc_tos(),
2746 "FAIL ! reply_readbraw: socket write fail (%s)",
2751 exit_server_cleanly(errstr);
2754 /****************************************************************************
2755 Fake (read/write) sendfile. Returns -1 on read or write fail.
2756 ****************************************************************************/
2758 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2762 size_t tosend = nread;
2769 bufsize = MIN(nread, 65536);
2771 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2775 while (tosend > 0) {
2779 if (tosend > bufsize) {
2784 ret = read_file(fsp,buf,startpos,cur_read);
2790 /* If we had a short read, fill with zeros. */
2791 if (ret < cur_read) {
2792 memset(buf + ret, '\0', cur_read - ret);
2795 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2800 startpos += cur_read;
2804 return (ssize_t)nread;
2807 #if defined(WITH_SENDFILE)
2808 /****************************************************************************
2809 Deal with the case of sendfile reading less bytes from the file than
2810 requested. Fill with zeros (all we can do).
2811 ****************************************************************************/
2813 static void sendfile_short_send(files_struct *fsp,
2818 #define SHORT_SEND_BUFSIZE 1024
2819 if (nread < headersize) {
2820 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2821 "header for file %s (%s). Terminating\n",
2822 fsp->fsp_name, strerror(errno) ));
2823 exit_server_cleanly("sendfile_short_send failed");
2826 nread -= headersize;
2828 if (nread < smb_maxcnt) {
2829 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2831 exit_server_cleanly("sendfile_short_send: "
2835 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2836 "with zeros !\n", fsp->fsp_name));
2838 while (nread < smb_maxcnt) {
2840 * We asked for the real file size and told sendfile
2841 * to not go beyond the end of the file. But it can
2842 * happen that in between our fstat call and the
2843 * sendfile call the file was truncated. This is very
2844 * bad because we have already announced the larger
2845 * number of bytes to the client.
2847 * The best we can do now is to send 0-bytes, just as
2848 * a read from a hole in a sparse file would do.
2850 * This should happen rarely enough that I don't care
2851 * about efficiency here :-)
2855 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2856 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2857 exit_server_cleanly("sendfile_short_send: "
2858 "write_data failed");
2865 #endif /* defined WITH_SENDFILE */
2867 /****************************************************************************
2868 Return a readbraw error (4 bytes of zero).
2869 ****************************************************************************/
2871 static void reply_readbraw_error(void)
2875 if (write_data(smbd_server_fd(),header,4) != 4) {
2880 /****************************************************************************
2881 Use sendfile in readbraw.
2882 ****************************************************************************/
2884 static void send_file_readbraw(connection_struct *conn,
2885 struct smb_request *req,
2891 char *outbuf = NULL;
2894 #if defined(WITH_SENDFILE)
2896 * We can only use sendfile on a non-chained packet
2897 * but we can use on a non-oplocked file. tridge proved this
2898 * on a train in Germany :-). JRA.
2899 * reply_readbraw has already checked the length.
2902 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2903 (fsp->wcp == NULL) &&
2904 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2905 ssize_t sendfile_read = -1;
2907 DATA_BLOB header_blob;
2909 _smb_setlen(header,nread);
2910 header_blob = data_blob_const(header, 4);
2912 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2913 &header_blob, startpos, nread)) == -1) {
2914 /* Returning ENOSYS means no data at all was sent.
2915 * Do this as a normal read. */
2916 if (errno == ENOSYS) {
2917 goto normal_readbraw;
2921 * Special hack for broken Linux with no working sendfile. If we
2922 * return EINTR we sent the header but not the rest of the data.
2923 * Fake this up by doing read/write calls.
2925 if (errno == EINTR) {
2926 /* Ensure we don't do this again. */
2927 set_use_sendfile(SNUM(conn), False);
2928 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2930 if (fake_sendfile(fsp, startpos, nread) == -1) {
2931 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2932 fsp->fsp_name, strerror(errno) ));
2933 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2938 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2939 fsp->fsp_name, strerror(errno) ));
2940 exit_server_cleanly("send_file_readbraw sendfile failed");
2941 } else if (sendfile_read == 0) {
2943 * Some sendfile implementations return 0 to indicate
2944 * that there was a short read, but nothing was
2945 * actually written to the socket. In this case,
2946 * fallback to the normal read path so the header gets
2947 * the correct byte count.
2949 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2950 "bytes falling back to the normal read: "
2951 "%s\n", fsp->fsp_name));
2952 goto normal_readbraw;
2955 /* Deal with possible short send. */
2956 if (sendfile_read != 4+nread) {
2957 sendfile_short_send(fsp, sendfile_read, 4, nread);
2965 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2967 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2968 (unsigned)(nread+4)));
2969 reply_readbraw_error();
2974 ret = read_file(fsp,outbuf+4,startpos,nread);
2975 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2984 _smb_setlen(outbuf,ret);
2985 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2988 TALLOC_FREE(outbuf);
2991 /****************************************************************************
2992 Reply to a readbraw (core+ protocol).
2993 ****************************************************************************/
2995 void reply_readbraw(struct smb_request *req)
2997 connection_struct *conn = req->conn;
2998 ssize_t maxcount,mincount;
3002 struct lock_struct lock;
3006 START_PROFILE(SMBreadbraw);
3008 if (srv_is_signing_active(smbd_server_conn) ||
3009 is_encrypted_packet(req->inbuf)) {
3010 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3011 "raw reads/writes are disallowed.");
3015 reply_readbraw_error();
3016 END_PROFILE(SMBreadbraw);
3021 * Special check if an oplock break has been issued
3022 * and the readraw request croses on the wire, we must
3023 * return a zero length response here.
3026 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3029 * We have to do a check_fsp by hand here, as
3030 * we must always return 4 zero bytes on error,
3034 if (!fsp || !conn || conn != fsp->conn ||
3035 req->vuid != fsp->vuid ||
3036 fsp->is_directory || fsp->fh->fd == -1) {
3038 * fsp could be NULL here so use the value from the packet. JRA.
3040 DEBUG(3,("reply_readbraw: fnum %d not valid "
3042 (int)SVAL(req->vwv+0, 0)));
3043 reply_readbraw_error();
3044 END_PROFILE(SMBreadbraw);
3048 /* Do a "by hand" version of CHECK_READ. */
3049 if (!(fsp->can_read ||
3050 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3051 (fsp->access_mask & FILE_EXECUTE)))) {
3052 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3053 (int)SVAL(req->vwv+0, 0)));
3054 reply_readbraw_error();
3055 END_PROFILE(SMBreadbraw);
3059 flush_write_cache(fsp, READRAW_FLUSH);
3061 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3062 if(req->wct == 10) {
3064 * This is a large offset (64 bit) read.
3066 #ifdef LARGE_SMB_OFF_T
3068 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3070 #else /* !LARGE_SMB_OFF_T */
3073 * Ensure we haven't been sent a >32 bit offset.
3076 if(IVAL(req->vwv+8, 0) != 0) {
3077 DEBUG(0,("reply_readbraw: large offset "
3078 "(%x << 32) used and we don't support "
3079 "64 bit offsets.\n",
3080 (unsigned int)IVAL(req->vwv+8, 0) ));
3081 reply_readbraw_error();
3082 END_PROFILE(SMBreadbraw);
3086 #endif /* LARGE_SMB_OFF_T */
3089 DEBUG(0,("reply_readbraw: negative 64 bit "
3090 "readraw offset (%.0f) !\n",
3091 (double)startpos ));
3092 reply_readbraw_error();
3093 END_PROFILE(SMBreadbraw);
3098 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3099 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3101 /* ensure we don't overrun the packet size */
3102 maxcount = MIN(65535,maxcount);
3104 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3105 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3108 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3109 reply_readbraw_error();
3110 END_PROFILE(SMBreadbraw);
3114 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3115 size = st.st_ex_size;
3118 if (startpos >= size) {
3121 nread = MIN(maxcount,(size - startpos));
3124 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3125 if (nread < mincount)
3129 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3130 "min=%lu nread=%lu\n",
3131 fsp->fnum, (double)startpos,
3132 (unsigned long)maxcount,
3133 (unsigned long)mincount,
3134 (unsigned long)nread ) );
3136 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3138 DEBUG(5,("reply_readbraw finished\n"));
3140 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3142 END_PROFILE(SMBreadbraw);
3147 #define DBGC_CLASS DBGC_LOCKING
3149 /****************************************************************************
3150 Reply to a lockread (core+ protocol).
3151 ****************************************************************************/
3153 void reply_lockread(struct smb_request *req)
3155 connection_struct *conn = req->conn;
3162 struct byte_range_lock *br_lck = NULL;
3164 struct smbd_server_connection *sconn = smbd_server_conn;
3166 START_PROFILE(SMBlockread);
3169 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3170 END_PROFILE(SMBlockread);
3174 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3176 if (!check_fsp(conn, req, fsp)) {
3177 END_PROFILE(SMBlockread);
3181 if (!CHECK_READ(fsp,req)) {
3182 reply_doserror(req, ERRDOS, ERRbadaccess);
3183 END_PROFILE(SMBlockread);
3187 numtoread = SVAL(req->vwv+1, 0);
3188 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3190 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3192 reply_outbuf(req, 5, numtoread + 3);
3194 data = smb_buf(req->outbuf) + 3;
3197 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3198 * protocol request that predates the read/write lock concept.
3199 * Thus instead of asking for a read lock here we need to ask
3200 * for a write lock. JRA.
3201 * Note that the requested lock size is unaffected by max_recv.
3204 br_lck = do_lock(smbd_messaging_context(),
3207 (uint64_t)numtoread,
3211 False, /* Non-blocking lock. */
3215 TALLOC_FREE(br_lck);
3217 if (NT_STATUS_V(status)) {
3218 reply_nterror(req, status);
3219 END_PROFILE(SMBlockread);
3224 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3227 if (numtoread > sconn->smb1.negprot.max_recv) {
3228 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3229 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3230 (unsigned int)numtoread,
3231 (unsigned int)sconn->smb1.negprot.max_recv));
3232 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3234 nread = read_file(fsp,data,startpos,numtoread);
3237 reply_unixerror(req, ERRDOS, ERRnoaccess);
3238 END_PROFILE(SMBlockread);
3242 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3244 SSVAL(req->outbuf,smb_vwv0,nread);
3245 SSVAL(req->outbuf,smb_vwv5,nread+3);
3246 p = smb_buf(req->outbuf);
3247 SCVAL(p,0,0); /* pad byte. */
3250 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3251 fsp->fnum, (int)numtoread, (int)nread));
3253 END_PROFILE(SMBlockread);
3258 #define DBGC_CLASS DBGC_ALL
3260 /****************************************************************************
3262 ****************************************************************************/
3264 void reply_read(struct smb_request *req)
3266 connection_struct *conn = req->conn;
3273 struct lock_struct lock;
3274 struct smbd_server_connection *sconn = smbd_server_conn;
3276 START_PROFILE(SMBread);
3279 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3280 END_PROFILE(SMBread);
3284 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3286 if (!check_fsp(conn, req, fsp)) {
3287 END_PROFILE(SMBread);
3291 if (!CHECK_READ(fsp,req)) {
3292 reply_doserror(req, ERRDOS, ERRbadaccess);
3293 END_PROFILE(SMBread);
3297 numtoread = SVAL(req->vwv+1, 0);
3298 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3300 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3303 * The requested read size cannot be greater than max_recv. JRA.
3305 if (numtoread > sconn->smb1.negprot.max_recv) {
3306 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3307 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3308 (unsigned int)numtoread,
3309 (unsigned int)sconn->smb1.negprot.max_recv));
3310 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3313 reply_outbuf(req, 5, numtoread+3);
3315 data = smb_buf(req->outbuf) + 3;
3317 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3318 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3321 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3322 reply_doserror(req, ERRDOS,ERRlock);
3323 END_PROFILE(SMBread);
3328 nread = read_file(fsp,data,startpos,numtoread);
3331 reply_unixerror(req, ERRDOS,ERRnoaccess);
3335 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3337 SSVAL(req->outbuf,smb_vwv0,nread);
3338 SSVAL(req->outbuf,smb_vwv5,nread+3);
3339 SCVAL(smb_buf(req->outbuf),0,1);
3340 SSVAL(smb_buf(req->outbuf),1,nread);
3342 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3343 fsp->fnum, (int)numtoread, (int)nread ) );
3346 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3348 END_PROFILE(SMBread);
3352 /****************************************************************************
3354 ****************************************************************************/
3356 static int setup_readX_header(struct smb_request *req, char *outbuf,
3362 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3363 data = smb_buf(outbuf);
3365 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3367 SCVAL(outbuf,smb_vwv0,0xFF);
3368 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3369 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3370 SSVAL(outbuf,smb_vwv6,
3372 + 1 /* the wct field */
3373 + 12 * sizeof(uint16_t) /* vwv */
3374 + 2); /* the buflen field */
3375 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3376 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3377 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3378 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3382 /****************************************************************************
3383 Reply to a read and X - possibly using sendfile.
3384 ****************************************************************************/
3386 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3387 files_struct *fsp, SMB_OFF_T startpos,
3390 SMB_STRUCT_STAT sbuf;
3392 struct lock_struct lock;
3394 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3395 reply_unixerror(req, ERRDOS, ERRnoaccess);
3399 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3400 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3403 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3404 reply_doserror(req, ERRDOS, ERRlock);
3408 if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
3409 || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
3411 * We already know that we would do a short read, so don't
3412 * try the sendfile() path.
3414 goto nosendfile_read;
3417 #if defined(WITH_SENDFILE)
3419 * We can only use sendfile on a non-chained packet
3420 * but we can use on a non-oplocked file. tridge proved this
3421 * on a train in Germany :-). JRA.
3424 if (!req_is_in_chain(req) &&
3425 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3426 (fsp->wcp == NULL) &&
3427 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3428 uint8 headerbuf[smb_size + 12 * 2];
3432 * Set up the packet header before send. We
3433 * assume here the sendfile will work (get the
3434 * correct amount of data).
3437 header = data_blob_const(headerbuf, sizeof(headerbuf));
3439 construct_reply_common_req(req, (char *)headerbuf);
3440 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3442 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3443 /* Returning ENOSYS means no data at all was sent.
3444 Do this as a normal read. */
3445 if (errno == ENOSYS) {
3450 * Special hack for broken Linux with no working sendfile. If we
3451 * return EINTR we sent the header but not the rest of the data.
3452 * Fake this up by doing read/write calls.
3455 if (errno == EINTR) {
3456 /* Ensure we don't do this again. */
3457 set_use_sendfile(SNUM(conn), False);
3458 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3459 nread = fake_sendfile(fsp, startpos,
3462 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3463 fsp->fsp_name, strerror(errno) ));
3464 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3466 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3467 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3468 /* No outbuf here means successful sendfile. */
3472 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3473 fsp->fsp_name, strerror(errno) ));
3474 exit_server_cleanly("send_file_readX sendfile failed");
3475 } else if (nread == 0) {
3477 * Some sendfile implementations return 0 to indicate
3478 * that there was a short read, but nothing was
3479 * actually written to the socket. In this case,
3480 * fallback to the normal read path so the header gets
3481 * the correct byte count.
3483 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3484 "falling back to the normal read: %s\n",
3489 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3490 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3492 /* Deal with possible short send. */
3493 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3494 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3496 /* No outbuf here means successful sendfile. */
3497 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3498 SMB_PERFCOUNT_END(&req->pcd);
3506 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3507 uint8 headerbuf[smb_size + 2*12];
3509 construct_reply_common_req(req, (char *)headerbuf);
3510 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3512 /* Send out the header. */
3513 if (write_data(smbd_server_fd(), (char *)headerbuf,
3514 sizeof(headerbuf)) != sizeof(headerbuf)) {
3515 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3516 fsp->fsp_name, strerror(errno) ));
3517 exit_server_cleanly("send_file_readX sendfile failed");
3519 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3521 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3522 fsp->fsp_name, strerror(errno) ));
3523 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3530 reply_outbuf(req, 12, smb_maxcnt);
3532 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3534 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3537 reply_unixerror(req, ERRDOS, ERRnoaccess);
3541 setup_readX_header(req, (char *)req->outbuf, nread);
3543 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3544 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3550 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3551 TALLOC_FREE(req->outbuf);
3555 /****************************************************************************
3556 Reply to a read and X.
3557 ****************************************************************************/
3559 void reply_read_and_X(struct smb_request *req)
3561 connection_struct *conn = req->conn;
3565 bool big_readX = False;
3567 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3570 START_PROFILE(SMBreadX);
3572 if ((req->wct != 10) && (req->wct != 12)) {
3573 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3577 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3578 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3579 smb_maxcnt = SVAL(req->vwv+5, 0);
3581 /* If it's an IPC, pass off the pipe handler. */
3583 reply_pipe_read_and_X(req);
3584 END_PROFILE(SMBreadX);
3588 if (!check_fsp(conn, req, fsp)) {
3589 END_PROFILE(SMBreadX);
3593 if (!CHECK_READ(fsp,req)) {
3594 reply_doserror(req, ERRDOS,ERRbadaccess);
3595 END_PROFILE(SMBreadX);
3599 if (global_client_caps & CAP_LARGE_READX) {
3600 size_t upper_size = SVAL(req->vwv+7, 0);
3601 smb_maxcnt |= (upper_size<<16);
3602 if (upper_size > 1) {
3603 /* Can't do this on a chained packet. */
3604 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3605 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3606 END_PROFILE(SMBreadX);
3609 /* We currently don't do this on signed or sealed data. */
3610 if (srv_is_signing_active(smbd_server_conn) ||
3611 is_encrypted_packet(req->inbuf)) {
3612 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3613 END_PROFILE(SMBreadX);
3616 /* Is there room in the reply for this data ? */
3617 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3619 NT_STATUS_INVALID_PARAMETER);
3620 END_PROFILE(SMBreadX);
3627 if (req->wct == 12) {
3628 #ifdef LARGE_SMB_OFF_T
3630 * This is a large offset (64 bit) read.
3632 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3634 #else /* !LARGE_SMB_OFF_T */
3637 * Ensure we haven't been sent a >32 bit offset.
3640 if(IVAL(req->vwv+10, 0) != 0) {
3641 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3642 "used and we don't support 64 bit offsets.\n",
3643 (unsigned int)IVAL(req->vwv+10, 0) ));
3644 END_PROFILE(SMBreadX);
3645 reply_doserror(req, ERRDOS, ERRbadaccess);
3649 #endif /* LARGE_SMB_OFF_T */
3654 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3658 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3661 END_PROFILE(SMBreadX);
3665 /****************************************************************************
3666 Error replies to writebraw must have smb_wct == 1. Fix this up.
3667 ****************************************************************************/
3669 void error_to_writebrawerr(struct smb_request *req)
3671 uint8 *old_outbuf = req->outbuf;
3673 reply_outbuf(req, 1, 0);
3675 memcpy(req->outbuf, old_outbuf, smb_size);
3676 TALLOC_FREE(old_outbuf);
3679 /****************************************************************************
3680 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3681 ****************************************************************************/
3683 void reply_writebraw(struct smb_request *req)
3685 connection_struct *conn = req->conn;
3688 ssize_t total_written=0;
3689 size_t numtowrite=0;
3695 struct lock_struct lock;
3698 START_PROFILE(SMBwritebraw);
3701 * If we ever reply with an error, it must have the SMB command
3702 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3705 SCVAL(req->inbuf,smb_com,SMBwritec);
3707 if (srv_is_signing_active(smbd_server_conn)) {
3708 END_PROFILE(SMBwritebraw);
3709 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3710 "raw reads/writes are disallowed.");
3713 if (req->wct < 12) {
3714 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3715 error_to_writebrawerr(req);
3716 END_PROFILE(SMBwritebraw);
3720 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3721 if (!check_fsp(conn, req, fsp)) {
3722 error_to_writebrawerr(req);
3723 END_PROFILE(SMBwritebraw);
3727 if (!CHECK_WRITE(fsp)) {
3728 reply_doserror(req, ERRDOS, ERRbadaccess);
3729 error_to_writebrawerr(req);
3730 END_PROFILE(SMBwritebraw);
3734 tcount = IVAL(req->vwv+1, 0);
3735 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3736 write_through = BITSETW(req->vwv+7,0);
3738 /* We have to deal with slightly different formats depending
3739 on whether we are using the core+ or lanman1.0 protocol */
3741 if(Protocol <= PROTOCOL_COREPLUS) {
3742 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3743 data = smb_buf(req->inbuf);
3745 numtowrite = SVAL(req->vwv+10, 0);
3746 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3749 /* Ensure we don't write bytes past the end of this packet. */
3750 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3751 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3752 error_to_writebrawerr(req);
3753 END_PROFILE(SMBwritebraw);
3757 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3758 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3761 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3762 reply_doserror(req, ERRDOS, ERRlock);
3763 error_to_writebrawerr(req);
3764 END_PROFILE(SMBwritebraw);
3769 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3772 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3773 "wrote=%d sync=%d\n",
3774 fsp->fnum, (double)startpos, (int)numtowrite,
3775 (int)nwritten, (int)write_through));
3777 if (nwritten < (ssize_t)numtowrite) {
3778 reply_unixerror(req, ERRHRD, ERRdiskfull);
3779 error_to_writebrawerr(req);
3783 total_written = nwritten;
3785 /* Allocate a buffer of 64k + length. */
3786 buf = TALLOC_ARRAY(NULL, char, 65540);
3788 reply_doserror(req, ERRDOS, ERRnomem);
3789 error_to_writebrawerr(req);
3793 /* Return a SMBwritebraw message to the redirector to tell
3794 * it to send more bytes */
3796 memcpy(buf, req->inbuf, smb_size);
3797 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3798 SCVAL(buf,smb_com,SMBwritebraw);
3799 SSVALS(buf,smb_vwv0,0xFFFF);
3801 if (!srv_send_smb(smbd_server_fd(),
3803 false, 0, /* no signing */
3804 IS_CONN_ENCRYPTED(conn),
3806 exit_server_cleanly("reply_writebraw: srv_send_smb "
3810 /* Now read the raw data into the buffer and write it */
3811 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3813 if (!NT_STATUS_IS_OK(status)) {
3814 exit_server_cleanly("secondary writebraw failed");
3817 /* Set up outbuf to return the correct size */
3818 reply_outbuf(req, 1, 0);
3820 if (numtowrite != 0) {
3822 if (numtowrite > 0xFFFF) {
3823 DEBUG(0,("reply_writebraw: Oversize secondary write "
3824 "raw requested (%u). Terminating\n",
3825 (unsigned int)numtowrite ));
3826 exit_server_cleanly("secondary writebraw failed");
3829 if (tcount > nwritten+numtowrite) {
3830 DEBUG(3,("reply_writebraw: Client overestimated the "
3832 (int)tcount,(int)nwritten,(int)numtowrite));
3835 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3837 if (!NT_STATUS_IS_OK(status)) {
3838 DEBUG(0,("reply_writebraw: Oversize secondary write "
3839 "raw read failed (%s). Terminating\n",
3840 nt_errstr(status)));
3841 exit_server_cleanly("secondary writebraw failed");
3844 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3845 if (nwritten == -1) {
3847 reply_unixerror(req, ERRHRD, ERRdiskfull);
3848 error_to_writebrawerr(req);
3852 if (nwritten < (ssize_t)numtowrite) {
3853 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3854 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3858 total_written += nwritten;
3863 SSVAL(req->outbuf,smb_vwv0,total_written);
3865 status = sync_file(conn, fsp, write_through);
3866 if (!NT_STATUS_IS_OK(status)) {
3867 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3868 fsp->fsp_name, nt_errstr(status) ));
3869 reply_nterror(req, status);
3870 error_to_writebrawerr(req);
3874 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3876 fsp->fnum, (double)startpos, (int)numtowrite,
3877 (int)total_written));
3879 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3881 /* We won't return a status if write through is not selected - this
3882 * follows what WfWg does */
3883 END_PROFILE(SMBwritebraw);
3885 if (!write_through && total_written==tcount) {
3887 #if RABBIT_PELLET_FIX
3889 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3890 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3893 if (!send_keepalive(smbd_server_fd())) {
3894 exit_server_cleanly("reply_writebraw: send of "
3895 "keepalive failed");
3898 TALLOC_FREE(req->outbuf);
3903 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3905 END_PROFILE(SMBwritebraw);
3910 #define DBGC_CLASS DBGC_LOCKING
3912 /****************************************************************************
3913 Reply to a writeunlock (core+).
3914 ****************************************************************************/
3916 void reply_writeunlock(struct smb_request *req)
3918 connection_struct *conn = req->conn;
3919 ssize_t nwritten = -1;
3923 NTSTATUS status = NT_STATUS_OK;
3925 struct lock_struct lock;
3927 START_PROFILE(SMBwriteunlock);
3930 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3931 END_PROFILE(SMBwriteunlock);
3935 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3937 if (!check_fsp(conn, req, fsp)) {
3938 END_PROFILE(SMBwriteunlock);
3942 if (!CHECK_WRITE(fsp)) {
3943 reply_doserror(req, ERRDOS,ERRbadaccess);
3944 END_PROFILE(SMBwriteunlock);
3948 numtowrite = SVAL(req->vwv+1, 0);
3949 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3950 data = (const char *)req->buf + 3;
3953 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3954 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3957 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3958 reply_doserror(req, ERRDOS, ERRlock);
3959 END_PROFILE(SMBwriteunlock);
3964 /* The special X/Open SMB protocol handling of
3965 zero length writes is *NOT* done for
3967 if(numtowrite == 0) {
3970 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3973 status = sync_file(conn, fsp, False /* write through */);
3974 if (!NT_STATUS_IS_OK(status)) {
3975 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3976 fsp->fsp_name, nt_errstr(status) ));
3977 reply_nterror(req, status);
3981 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3982 reply_unixerror(req, ERRHRD, ERRdiskfull);
3987 status = do_unlock(smbd_messaging_context(),
3990 (uint64_t)numtowrite,
3994 if (NT_STATUS_V(status)) {
3995 reply_nterror(req, status);
4000 reply_outbuf(req, 1, 0);
4002 SSVAL(req->outbuf,smb_vwv0,nwritten);
4004 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4005 fsp->fnum, (int)numtowrite, (int)nwritten));
4009 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4012 END_PROFILE(SMBwriteunlock);
4017 #define DBGC_CLASS DBGC_ALL
4019 /****************************************************************************
4021 ****************************************************************************/
4023 void reply_write(struct smb_request *req)
4025 connection_struct *conn = req->conn;
4027 ssize_t nwritten = -1;
4031 struct lock_struct lock;
4034 START_PROFILE(SMBwrite);
4037 END_PROFILE(SMBwrite);
4038 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4042 /* If it's an IPC, pass off the pipe handler. */
4044 reply_pipe_write(req);
4045 END_PROFILE(SMBwrite);
4049 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4051 if (!check_fsp(conn, req, fsp)) {
4052 END_PROFILE(SMBwrite);
4056 if (!CHECK_WRITE(fsp)) {
4057 reply_doserror(req, ERRDOS, ERRbadaccess);
4058 END_PROFILE(SMBwrite);
4062 numtowrite = SVAL(req->vwv+1, 0);
4063 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4064 data = (const char *)req->buf + 3;
4066 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4067 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4070 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4071 reply_doserror(req, ERRDOS, ERRlock);
4072 END_PROFILE(SMBwrite);
4077 * X/Open SMB protocol says that if smb_vwv1 is
4078 * zero then the file size should be extended or
4079 * truncated to the size given in smb_vwv[2-3].
4082 if(numtowrite == 0) {
4084 * This is actually an allocate call, and set EOF. JRA.
4086 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4088 reply_nterror(req, NT_STATUS_DISK_FULL);
4091 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4093 reply_nterror(req, NT_STATUS_DISK_FULL);
4096 trigger_write_time_update_immediate(fsp);
4098 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4101 status = sync_file(conn, fsp, False);
4102 if (!NT_STATUS_IS_OK(status)) {
4103 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4104 fsp->fsp_name, nt_errstr(status) ));
4105 reply_nterror(req, status);
4109 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4110 reply_unixerror(req, ERRHRD, ERRdiskfull);
4114 reply_outbuf(req, 1, 0);
4116 SSVAL(req->outbuf,smb_vwv0,nwritten);
4118 if (nwritten < (ssize_t)numtowrite) {
4119 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4120 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4123 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4126 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4128 END_PROFILE(SMBwrite);
4132 /****************************************************************************
4133 Ensure a buffer is a valid writeX for recvfile purposes.
4134 ****************************************************************************/
4136 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4137 (2*14) + /* word count (including bcc) */ \
4140 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4143 connection_struct *conn = NULL;
4144 unsigned int doff = 0;
4145 size_t len = smb_len_large(inbuf);
4146 struct smbd_server_connection *sconn = smbd_server_conn;
4148 if (is_encrypted_packet(inbuf)) {
4149 /* Can't do this on encrypted
4154 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4158 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4159 CVAL(inbuf,smb_wct) != 14) {
4160 DEBUG(10,("is_valid_writeX_buffer: chained or "
4161 "invalid word length.\n"));
4165 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4167 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4171 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4174 if (IS_PRINT(conn)) {
4175 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4178 doff = SVAL(inbuf,smb_vwv11);
4180 numtowrite = SVAL(inbuf,smb_vwv10);
4182 if (len > doff && len - doff > 0xFFFF) {
4183 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4186 if (numtowrite == 0) {
4187 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4191 /* Ensure the sizes match up. */
4192 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4193 /* no pad byte...old smbclient :-( */
4194 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4196 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4200 if (len - doff != numtowrite) {
4201 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4202 "len = %u, doff = %u, numtowrite = %u\n",
4205 (unsigned int)numtowrite ));
4209 DEBUG(10,("is_valid_writeX_buffer: true "
4210 "len = %u, doff = %u, numtowrite = %u\n",
4213 (unsigned int)numtowrite ));
4218 /****************************************************************************
4219 Reply to a write and X.
4220 ****************************************************************************/
4222 void reply_write_and_X(struct smb_request *req)
4224 connection_struct *conn = req->conn;
4226 struct lock_struct lock;
4231 unsigned int smb_doff;
4232 unsigned int smblen;
4236 START_PROFILE(SMBwriteX);
4238 if ((req->wct != 12) && (req->wct != 14)) {
4239 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4240 END_PROFILE(SMBwriteX);
4244 numtowrite = SVAL(req->vwv+10, 0);
4245 smb_doff = SVAL(req->vwv+11, 0);
4246 smblen = smb_len(req->inbuf);
4248 if (req->unread_bytes > 0xFFFF ||
4249 (smblen > smb_doff &&
4250 smblen - smb_doff > 0xFFFF)) {
4251 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4254 if (req->unread_bytes) {
4255 /* Can't do a recvfile write on IPC$ */
4257 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4258 END_PROFILE(SMBwriteX);
4261 if (numtowrite != req->unread_bytes) {
4262 reply_doserror(req, ERRDOS, ERRbadmem);
4263 END_PROFILE(SMBwriteX);
4267 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4268 smb_doff + numtowrite > smblen) {
4269 reply_doserror(req, ERRDOS, ERRbadmem);
4270 END_PROFILE(SMBwriteX);
4275 /* If it's an IPC, pass off the pipe handler. */
4277 if (req->unread_bytes) {
4278 reply_doserror(req, ERRDOS, ERRbadmem);
4279 END_PROFILE(SMBwriteX);
4282 reply_pipe_write_and_X(req);
4283 END_PROFILE(SMBwriteX);
4287 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4288 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4289 write_through = BITSETW(req->vwv+7,0);
4291 if (!check_fsp(conn, req, fsp)) {
4292 END_PROFILE(SMBwriteX);
4296 if (!CHECK_WRITE(fsp)) {
4297 reply_doserror(req, ERRDOS, ERRbadaccess);
4298 END_PROFILE(SMBwriteX);
4302 data = smb_base(req->inbuf) + smb_doff;
4304 if(req->wct == 14) {
4305 #ifdef LARGE_SMB_OFF_T
4307 * This is a large offset (64 bit) write.
4309 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4311 #else /* !LARGE_SMB_OFF_T */
4314 * Ensure we haven't been sent a >32 bit offset.
4317 if(IVAL(req->vwv+12, 0) != 0) {
4318 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4319 "used and we don't support 64 bit offsets.\n",
4320 (unsigned int)IVAL(req->vwv+12, 0) ));
4321 reply_doserror(req, ERRDOS, ERRbadaccess);
4322 END_PROFILE(SMBwriteX);
4326 #endif /* LARGE_SMB_OFF_T */
4329 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4330 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4333 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4334 reply_doserror(req, ERRDOS, ERRlock);
4335 END_PROFILE(SMBwriteX);
4339 /* X/Open SMB protocol says that, unlike SMBwrite
4340 if the length is zero then NO truncation is
4341 done, just a write of zero. To truncate a file,
4344 if(numtowrite == 0) {
4348 if ((req->unread_bytes == 0) &&
4349 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4354 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4357 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4358 reply_unixerror(req, ERRHRD, ERRdiskfull);
4362 reply_outbuf(req, 6, 0);
4363 SSVAL(req->outbuf,smb_vwv2,nwritten);
4364 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4366 if (nwritten < (ssize_t)numtowrite) {
4367 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4368 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4371 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4372 fsp->fnum, (int)numtowrite, (int)nwritten));
4374 status = sync_file(conn, fsp, write_through);
4375 if (!NT_STATUS_IS_OK(status)) {
4376 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4377 fsp->fsp_name, nt_errstr(status) ));
4378 reply_nterror(req, status);
4382 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4384 END_PROFILE(SMBwriteX);
4389 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4391 END_PROFILE(SMBwriteX);
4395 /****************************************************************************
4397 ****************************************************************************/
4399 void reply_lseek(struct smb_request *req)
4401 connection_struct *conn = req->conn;
4407 START_PROFILE(SMBlseek);
4410 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4411 END_PROFILE(SMBlseek);
4415 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4417 if (!check_fsp(conn, req, fsp)) {
4421 flush_write_cache(fsp, SEEK_FLUSH);
4423 mode = SVAL(req->vwv+1, 0) & 3;
4424 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4425 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4434 res = fsp->fh->pos + startpos;
4445 if (umode == SEEK_END) {
4446 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4447 if(errno == EINVAL) {
4448 SMB_OFF_T current_pos = startpos;
4449 SMB_STRUCT_STAT sbuf;
4451 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4452 reply_unixerror(req, ERRDOS,
4454 END_PROFILE(SMBlseek);
4458 current_pos += sbuf.st_ex_size;
4460 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4465 reply_unixerror(req, ERRDOS, ERRnoaccess);
4466 END_PROFILE(SMBlseek);
4473 reply_outbuf(req, 2, 0);
4474 SIVAL(req->outbuf,smb_vwv0,res);
4476 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4477 fsp->fnum, (double)startpos, (double)res, mode));
4479 END_PROFILE(SMBlseek);
4483 /****************************************************************************
4485 ****************************************************************************/
4487 void reply_flush(struct smb_request *req)
4489 connection_struct *conn = req->conn;
4493 START_PROFILE(SMBflush);
4496 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4500 fnum = SVAL(req->vwv+0, 0);
4501 fsp = file_fsp(req, fnum);
4503 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4508 file_sync_all(conn);
4510 NTSTATUS status = sync_file(conn, fsp, True);
4511 if (!NT_STATUS_IS_OK(status)) {
4512 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4513 fsp->fsp_name, nt_errstr(status) ));
4514 reply_nterror(req, status);
4515 END_PROFILE(SMBflush);
4520 reply_outbuf(req, 0, 0);
4522 DEBUG(3,("flush\n"));
4523 END_PROFILE(SMBflush);
4527 /****************************************************************************
4529 conn POINTER CAN BE NULL HERE !
4530 ****************************************************************************/
4532 void reply_exit(struct smb_request *req)
4534 START_PROFILE(SMBexit);
4536 file_close_pid(req->smbpid, req->vuid);
4538 reply_outbuf(req, 0, 0);
4540 DEBUG(3,("exit\n"));
4542 END_PROFILE(SMBexit);
4546 /****************************************************************************
4547 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4548 ****************************************************************************/
4550 void reply_close(struct smb_request *req)
4552 connection_struct *conn = req->conn;
4553 NTSTATUS status = NT_STATUS_OK;
4554 files_struct *fsp = NULL;
4555 START_PROFILE(SMBclose);
4558 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4559 END_PROFILE(SMBclose);
4563 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4566 * We can only use check_fsp if we know it's not a directory.
4569 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4570 reply_doserror(req, ERRDOS, ERRbadfid);
4571 END_PROFILE(SMBclose);
4575 if(fsp->is_directory) {
4577 * Special case - close NT SMB directory handle.
4579 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4580 status = close_file(req, fsp, NORMAL_CLOSE);
4584 * Close ordinary file.
4587 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4588 fsp->fh->fd, fsp->fnum,
4589 conn->num_files_open));
4592 * Take care of any time sent in the close.
4595 t = srv_make_unix_date3(req->vwv+1);
4596 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4599 * close_file() returns the unix errno if an error
4600 * was detected on close - normally this is due to
4601 * a disk full error. If not then it was probably an I/O error.
4604 status = close_file(req, fsp, NORMAL_CLOSE);
4607 if (!NT_STATUS_IS_OK(status)) {
4608 reply_nterror(req, status);
4609 END_PROFILE(SMBclose);
4613 reply_outbuf(req, 0, 0);
4614 END_PROFILE(SMBclose);
4618 /****************************************************************************
4619 Reply to a writeclose (Core+ protocol).
4620 ****************************************************************************/
4622 void reply_writeclose(struct smb_request *req)
4624 connection_struct *conn = req->conn;
4626 ssize_t nwritten = -1;
4627 NTSTATUS close_status = NT_STATUS_OK;
4630 struct timespec mtime;
4632 struct lock_struct lock;
4634 START_PROFILE(SMBwriteclose);
4637 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4638 END_PROFILE(SMBwriteclose);
4642 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4644 if (!check_fsp(conn, req, fsp)) {
4645 END_PROFILE(SMBwriteclose);
4648 if (!CHECK_WRITE(fsp)) {
4649 reply_doserror(req, ERRDOS,ERRbadaccess);
4650 END_PROFILE(SMBwriteclose);
4654 numtowrite = SVAL(req->vwv+1, 0);
4655 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4656 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4657 data = (const char *)req->buf + 1;
4660 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4661 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4664 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4665 reply_doserror(req, ERRDOS,ERRlock);
4666 END_PROFILE(SMBwriteclose);
4671 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4673 set_close_write_time(fsp, mtime);
4676 * More insanity. W2K only closes the file if writelen > 0.
4681 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4683 close_status = close_file(req, fsp, NORMAL_CLOSE);
4686 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4687 fsp->fnum, (int)numtowrite, (int)nwritten,
4688 conn->num_files_open));
4690 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4691 reply_doserror(req, ERRHRD, ERRdiskfull);
4695 if(!NT_STATUS_IS_OK(close_status)) {
4696 reply_nterror(req, close_status);
4700 reply_outbuf(req, 1, 0);
4702 SSVAL(req->outbuf,smb_vwv0,nwritten);
4706 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4709 END_PROFILE(SMBwriteclose);
4714 #define DBGC_CLASS DBGC_LOCKING
4716 /****************************************************************************
4718 ****************************************************************************/
4720 void reply_lock(struct smb_request *req)
4722 connection_struct *conn = req->conn;
4723 uint64_t count,offset;
4726 struct byte_range_lock *br_lck = NULL;
4728 START_PROFILE(SMBlock);
4731 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4732 END_PROFILE(SMBlock);
4736 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4738 if (!check_fsp(conn, req, fsp)) {
4739 END_PROFILE(SMBlock);
4743 count = (uint64_t)IVAL(req->vwv+1, 0);
4744 offset = (uint64_t)IVAL(req->vwv+3, 0);
4746 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4747 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4749 br_lck = do_lock(smbd_messaging_context(),
4756 False, /* Non-blocking lock. */
4761 TALLOC_FREE(br_lck);
4763 if (NT_STATUS_V(status)) {
4764 reply_nterror(req, status);
4765 END_PROFILE(SMBlock);
4769 reply_outbuf(req, 0, 0);
4771 END_PROFILE(SMBlock);
4775 /****************************************************************************
4777 ****************************************************************************/
4779 void reply_unlock(struct smb_request *req)
4781 connection_struct *conn = req->conn;
4782 uint64_t count,offset;
4786 START_PROFILE(SMBunlock);
4789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4790 END_PROFILE(SMBunlock);
4794 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4796 if (!check_fsp(conn, req, fsp)) {
4797 END_PROFILE(SMBunlock);
4801 count = (uint64_t)IVAL(req->vwv+1, 0);
4802 offset = (uint64_t)IVAL(req->vwv+3, 0);
4804 status = do_unlock(smbd_messaging_context(),
4811 if (NT_STATUS_V(status)) {
4812 reply_nterror(req, status);
4813 END_PROFILE(SMBunlock);
4817 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4818 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4820 reply_outbuf(req, 0, 0);
4822 END_PROFILE(SMBunlock);
4827 #define DBGC_CLASS DBGC_ALL
4829 /****************************************************************************
4831 conn POINTER CAN BE NULL HERE !
4832 ****************************************************************************/
4834 void reply_tdis(struct smb_request *req)
4836 struct smbd_server_connection *sconn = smbd_server_conn;
4837 connection_struct *conn = req->conn;
4838 START_PROFILE(SMBtdis);
4841 DEBUG(4,("Invalid connection in tdis\n"));
4842 reply_doserror(req, ERRSRV, ERRinvnid);
4843 END_PROFILE(SMBtdis);
4849 close_cnum(sconn, conn,req->vuid);
4852 reply_outbuf(req, 0, 0);
4853 END_PROFILE(SMBtdis);
4857 /****************************************************************************
4859 conn POINTER CAN BE NULL HERE !
4860 ****************************************************************************/
4862 void reply_echo(struct smb_request *req)
4864 connection_struct *conn = req->conn;
4865 struct smb_perfcount_data local_pcd;
4866 struct smb_perfcount_data *cur_pcd;
4870 START_PROFILE(SMBecho);
4872 smb_init_perfcount_data(&local_pcd);
4875 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4876 END_PROFILE(SMBecho);
4880 smb_reverb = SVAL(req->vwv+0, 0);
4882 reply_outbuf(req, 1, req->buflen);
4884 /* copy any incoming data back out */
4885 if (req->buflen > 0) {
4886 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4889 if (smb_reverb > 100) {
4890 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4894 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4896 /* this makes sure we catch the request pcd */
4897 if (seq_num == smb_reverb) {
4898 cur_pcd = &req->pcd;
4900 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4901 cur_pcd = &local_pcd;
4904 SSVAL(req->outbuf,smb_vwv0,seq_num);
4906 show_msg((char *)req->outbuf);
4907 if (!srv_send_smb(smbd_server_fd(),
4908 (char *)req->outbuf,
4909 true, req->seqnum+1,
4910 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4912 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4915 DEBUG(3,("echo %d times\n", smb_reverb));
4917 TALLOC_FREE(req->outbuf);
4919 END_PROFILE(SMBecho);
4923 /****************************************************************************
4924 Reply to a printopen.
4925 ****************************************************************************/
4927 void reply_printopen(struct smb_request *req)
4929 connection_struct *conn = req->conn;
4931 SMB_STRUCT_STAT sbuf;
4934 START_PROFILE(SMBsplopen);
4937 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4938 END_PROFILE(SMBsplopen);
4942 if (!CAN_PRINT(conn)) {
4943 reply_doserror(req, ERRDOS, ERRnoaccess);
4944 END_PROFILE(SMBsplopen);
4948 status = file_new(req, conn, &fsp);
4949 if(!NT_STATUS_IS_OK(status)) {
4950 reply_nterror(req, status);
4951 END_PROFILE(SMBsplopen);
4955 /* Open for exclusive use, write only. */
4956 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4958 if (!NT_STATUS_IS_OK(status)) {
4959 file_free(req, fsp);
4960 reply_nterror(req, status);
4961 END_PROFILE(SMBsplopen);
4965 reply_outbuf(req, 1, 0);
4966 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4968 DEBUG(3,("openprint fd=%d fnum=%d\n",
4969 fsp->fh->fd, fsp->fnum));
4971 END_PROFILE(SMBsplopen);
4975 /****************************************************************************
4976 Reply to a printclose.
4977 ****************************************************************************/
4979 void reply_printclose(struct smb_request *req)
4981 connection_struct *conn = req->conn;
4985 START_PROFILE(SMBsplclose);
4988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4989 END_PROFILE(SMBsplclose);
4993 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4995 if (!check_fsp(conn, req, fsp)) {
4996 END_PROFILE(SMBsplclose);
5000 if (!CAN_PRINT(conn)) {
5001 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
5002 END_PROFILE(SMBsplclose);
5006 DEBUG(3,("printclose fd=%d fnum=%d\n",
5007 fsp->fh->fd,fsp->fnum));
5009 status = close_file(req, fsp, NORMAL_CLOSE);
5011 if(!NT_STATUS_IS_OK(status)) {
5012 reply_nterror(req, status);
5013 END_PROFILE(SMBsplclose);
5017 reply_outbuf(req, 0, 0);
5019 END_PROFILE(SMBsplclose);
5023 /****************************************************************************
5024 Reply to a printqueue.
5025 ****************************************************************************/
5027 void reply_printqueue(struct smb_request *req)
5029 connection_struct *conn = req->conn;
5033 START_PROFILE(SMBsplretq);
5036 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5037 END_PROFILE(SMBsplretq);
5041 max_count = SVAL(req->vwv+0, 0);
5042 start_index = SVAL(req->vwv+1, 0);
5044 /* we used to allow the client to get the cnum wrong, but that
5045 is really quite gross and only worked when there was only
5046 one printer - I think we should now only accept it if they
5047 get it right (tridge) */
5048 if (!CAN_PRINT(conn)) {
5049 reply_doserror(req, ERRDOS, ERRnoaccess);
5050 END_PROFILE(SMBsplretq);
5054 reply_outbuf(req, 2, 3);
5055 SSVAL(req->outbuf,smb_vwv0,0);
5056 SSVAL(req->outbuf,smb_vwv1,0);
5057 SCVAL(smb_buf(req->outbuf),0,1);
5058 SSVAL(smb_buf(req->outbuf),1,0);
5060 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5061 start_index, max_count));
5064 print_queue_struct *queue = NULL;
5065 print_status_struct status;
5066 int count = print_queue_status(SNUM(conn), &queue, &status);
5067 int num_to_get = ABS(max_count);
5068 int first = (max_count>0?start_index:start_index+max_count+1);
5074 num_to_get = MIN(num_to_get,count-first);
5077 for (i=first;i<first+num_to_get;i++) {
5081 srv_put_dos_date2(p,0,queue[i].time);
5082 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5083 SSVAL(p,5, queue[i].job);
5084 SIVAL(p,7,queue[i].size);
5086 srvstr_push(blob, req->flags2, p+12,
5087 queue[i].fs_user, 16, STR_ASCII);
5089 if (message_push_blob(
5092 blob, sizeof(blob))) == -1) {
5093 reply_nterror(req, NT_STATUS_NO_MEMORY);
5094 END_PROFILE(SMBsplretq);
5100 SSVAL(req->outbuf,smb_vwv0,count);
5101 SSVAL(req->outbuf,smb_vwv1,
5102 (max_count>0?first+count:first-1));
5103 SCVAL(smb_buf(req->outbuf),0,1);
5104 SSVAL(smb_buf(req->outbuf),1,28*count);
5109 DEBUG(3,("%d entries returned in queue\n",count));
5112 END_PROFILE(SMBsplretq);
5116 /****************************************************************************
5117 Reply to a printwrite.
5118 ****************************************************************************/
5120 void reply_printwrite(struct smb_request *req)
5122 connection_struct *conn = req->conn;
5127 START_PROFILE(SMBsplwr);
5130 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5131 END_PROFILE(SMBsplwr);
5135 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5137 if (!check_fsp(conn, req, fsp)) {
5138 END_PROFILE(SMBsplwr);
5142 if (!CAN_PRINT(conn)) {
5143 reply_doserror(req, ERRDOS, ERRnoaccess);
5144 END_PROFILE(SMBsplwr);
5148 if (!CHECK_WRITE(fsp)) {
5149 reply_doserror(req, ERRDOS, ERRbadaccess);
5150 END_PROFILE(SMBsplwr);
5154 numtowrite = SVAL(req->buf, 1);
5156 if (req->buflen < numtowrite + 3) {
5157 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5158 END_PROFILE(SMBsplwr);
5162 data = (const char *)req->buf + 3;
5164 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5165 reply_unixerror(req, ERRHRD, ERRdiskfull);
5166 END_PROFILE(SMBsplwr);
5170 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5172 END_PROFILE(SMBsplwr);
5176 /****************************************************************************
5178 ****************************************************************************/
5180 void reply_mkdir(struct smb_request *req)
5182 connection_struct *conn = req->conn;
5183 struct smb_filename *smb_dname = NULL;
5184 char *directory = NULL;
5186 TALLOC_CTX *ctx = talloc_tos();
5188 START_PROFILE(SMBmkdir);
5190 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5191 STR_TERMINATE, &status);
5192 if (!NT_STATUS_IS_OK(status)) {
5193 reply_nterror(req, status);
5197 status = filename_convert(ctx, conn,
5198 req->flags2 & FLAGS2_DFS_PATHNAMES,
5202 if (!NT_STATUS_IS_OK(status)) {
5203 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5204 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5205 ERRSRV, ERRbadpath);
5208 reply_nterror(req, status);
5212 status = create_directory(conn, req, smb_dname);
5214 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5216 if (!NT_STATUS_IS_OK(status)) {
5218 if (!use_nt_status()
5219 && NT_STATUS_EQUAL(status,
5220 NT_STATUS_OBJECT_NAME_COLLISION)) {
5222 * Yes, in the DOS error code case we get a
5223 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5224 * samba4 torture test.
5226 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5229 reply_nterror(req, status);
5233 reply_outbuf(req, 0, 0);
5235 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5237 TALLOC_FREE(smb_dname);
5238 END_PROFILE(SMBmkdir);
5242 /****************************************************************************
5243 Static function used by reply_rmdir to delete an entire directory
5244 tree recursively. Return True on ok, False on fail.
5245 ****************************************************************************/
5247 static bool recursive_rmdir(TALLOC_CTX *ctx,
5248 connection_struct *conn,
5249 struct smb_filename *smb_dname)
5251 const char *dname = NULL;
5255 struct smb_Dir *dir_hnd;
5257 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5259 dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0);
5263 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5264 struct smb_filename *smb_dname_full = NULL;
5265 char *fullname = NULL;
5266 bool do_break = true;
5269 if (ISDOT(dname) || ISDOTDOT(dname)) {
5273 if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
5278 /* Construct the full name. */
5279 fullname = talloc_asprintf(ctx,
5281 smb_dname->base_name,
5288 status = create_synthetic_smb_fname(talloc_tos(), fullname,
5291 if (!NT_STATUS_IS_OK(status)) {
5295 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5299 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5300 if(!recursive_rmdir(ctx, conn, smb_dname_full)) {
5303 if(SMB_VFS_RMDIR(conn,
5304 smb_dname_full->base_name) != 0) {
5307 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5311 /* Successful iteration. */
5315 TALLOC_FREE(smb_dname_full);
5316 TALLOC_FREE(fullname);
5322 TALLOC_FREE(dir_hnd);
5326 /****************************************************************************
5327 The internals of the rmdir code - called elsewhere.
5328 ****************************************************************************/
5330 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5331 connection_struct *conn,
5332 struct smb_filename *smb_dname)
5337 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5339 /* Might be a symlink. */
5340 if(SMB_VFS_LSTAT(conn, smb_dname) != 0) {
5341 return map_nt_error_from_unix(errno);
5344 if (S_ISLNK(smb_dname->st.st_ex_mode)) {
5345 /* Is what it points to a directory ? */
5346 if(SMB_VFS_STAT(conn, smb_dname) != 0) {
5347 return map_nt_error_from_unix(errno);
5349 if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
5350 return NT_STATUS_NOT_A_DIRECTORY;
5352 ret = SMB_VFS_UNLINK(conn, smb_dname);
5354 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5357 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5358 FILE_NOTIFY_CHANGE_DIR_NAME,
5359 smb_dname->base_name);
5360 return NT_STATUS_OK;
5363 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5365 * Check to see if the only thing in this directory are
5366 * vetoed files/directories. If so then delete them and
5367 * retry. If we fail to delete any of them (and we *don't*
5368 * do a recursive delete) then fail the rmdir.
5372 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5373 smb_dname->base_name, NULL,
5376 if(dir_hnd == NULL) {
5381 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5382 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5384 if (!is_visible_file(conn, smb_dname->base_name, dname,
5387 if(!IS_VETO_PATH(conn, dname)) {
5388 TALLOC_FREE(dir_hnd);
5394 /* We only have veto files/directories.
5395 * Are we allowed to delete them ? */
5397 if(!lp_recursive_veto_delete(SNUM(conn))) {
5398 TALLOC_FREE(dir_hnd);
5403 /* Do a recursive delete. */
5404 RewindDir(dir_hnd,&dirpos);
5405 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5406 struct smb_filename *smb_dname_full = NULL;
5407 char *fullname = NULL;
5408 bool do_break = true;
5411 if (ISDOT(dname) || ISDOTDOT(dname)) {
5414 if (!is_visible_file(conn, smb_dname->base_name, dname,
5419 fullname = talloc_asprintf(ctx,
5421 smb_dname->base_name,
5429 status = create_synthetic_smb_fname(talloc_tos(),
5433 if (!NT_STATUS_IS_OK(status)) {
5434 errno = map_errno_from_nt_status(status);
5438 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5441 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5442 if(!recursive_rmdir(ctx, conn,
5446 if(SMB_VFS_RMDIR(conn,
5447 smb_dname_full->base_name) != 0) {
5450 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5454 /* Successful iteration. */
5458 TALLOC_FREE(fullname);
5459 TALLOC_FREE(smb_dname_full);
5463 TALLOC_FREE(dir_hnd);
5464 /* Retry the rmdir */
5465 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5471 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5472 "%s\n", smb_fname_str_dbg(smb_dname),
5474 return map_nt_error_from_unix(errno);
5477 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5478 FILE_NOTIFY_CHANGE_DIR_NAME,
5479 smb_dname->base_name);
5481 return NT_STATUS_OK;
5484 /****************************************************************************
5486 ****************************************************************************/
5488 void reply_rmdir(struct smb_request *req)
5490 connection_struct *conn = req->conn;
5491 struct smb_filename *smb_dname = NULL;
5492 char *directory = NULL;
5494 TALLOC_CTX *ctx = talloc_tos();
5496 START_PROFILE(SMBrmdir);
5498 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5499 STR_TERMINATE, &status);
5500 if (!NT_STATUS_IS_OK(status)) {
5501 reply_nterror(req, status);
5505 status = filename_convert(ctx, conn,
5506 req->flags2 & FLAGS2_DFS_PATHNAMES,
5510 if (!NT_STATUS_IS_OK(status)) {
5511 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5512 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5513 ERRSRV, ERRbadpath);
5516 reply_nterror(req, status);
5520 dptr_closepath(directory, req->smbpid);
5521 status = rmdir_internals(ctx, conn, smb_dname);
5522 if (!NT_STATUS_IS_OK(status)) {
5523 reply_nterror(req, status);
5527 reply_outbuf(req, 0, 0);
5529 DEBUG( 3, ( "rmdir %s\n", directory ) );
5531 TALLOC_FREE(smb_dname);
5532 END_PROFILE(SMBrmdir);
5536 /*******************************************************************
5537 Resolve wildcards in a filename rename.
5538 ********************************************************************/
5540 static bool resolve_wildcards(TALLOC_CTX *ctx,
5545 char *name2_copy = NULL;
5550 char *p,*p2, *pname1, *pname2;
5552 name2_copy = talloc_strdup(ctx, name2);
5557 pname1 = strrchr_m(name1,'/');
5558 pname2 = strrchr_m(name2_copy,'/');
5560 if (!pname1 || !pname2) {
5564 /* Truncate the copy of name2 at the last '/' */
5567 /* Now go past the '/' */
5571 root1 = talloc_strdup(ctx, pname1);
5572 root2 = talloc_strdup(ctx, pname2);
5574 if (!root1 || !root2) {
5578 p = strrchr_m(root1,'.');
5581 ext1 = talloc_strdup(ctx, p+1);
5583 ext1 = talloc_strdup(ctx, "");
5585 p = strrchr_m(root2,'.');
5588 ext2 = talloc_strdup(ctx, p+1);
5590 ext2 = talloc_strdup(ctx, "");
5593 if (!ext1 || !ext2) {
5601 /* Hmmm. Should this be mb-aware ? */
5604 } else if (*p2 == '*') {
5606 root2 = talloc_asprintf(ctx, "%s%s",
5625 /* Hmmm. Should this be mb-aware ? */
5628 } else if (*p2 == '*') {
5630 ext2 = talloc_asprintf(ctx, "%s%s",
5646 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5651 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5663 /****************************************************************************
5664 Ensure open files have their names updated. Updated to notify other smbd's
5666 ****************************************************************************/
5668 static void rename_open_files(connection_struct *conn,
5669 struct share_mode_lock *lck,
5670 const struct smb_filename *smb_fname_dst)
5673 bool did_rename = False;
5674 char *fname_dst = NULL;
5677 status = get_full_smb_filename(talloc_tos(), smb_fname_dst,
5679 if (!NT_STATUS_IS_OK(status)) {
5683 for(fsp = file_find_di_first(lck->id); fsp;
5684 fsp = file_find_di_next(fsp)) {
5685 /* fsp_name is a relative path under the fsp. To change this for other
5686 sharepaths we need to manipulate relative paths. */
5687 /* TODO - create the absolute path and manipulate the newname
5688 relative to the sharepath. */
5689 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5692 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5693 "(file_id %s) from %s -> %s\n", fsp->fnum,
5694 file_id_string_tos(&fsp->file_id), fsp->fsp_name,
5695 smb_fname_str_dbg(smb_fname_dst)));
5696 string_set(&fsp->fsp_name, fname_dst);
5701 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5702 "for %s\n", file_id_string_tos(&lck->id),
5703 smb_fname_str_dbg(smb_fname_dst)));
5706 /* Send messages to all smbd's (not ourself) that the name has changed. */
5707 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5709 TALLOC_FREE(fname_dst);
5712 /****************************************************************************
5713 We need to check if the source path is a parent directory of the destination
5714 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5715 refuse the rename with a sharing violation. Under UNIX the above call can
5716 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5717 probably need to check that the client is a Windows one before disallowing
5718 this as a UNIX client (one with UNIX extensions) can know the source is a
5719 symlink and make this decision intelligently. Found by an excellent bug
5720 report from <AndyLiebman@aol.com>.
5721 ****************************************************************************/
5723 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5724 const struct smb_filename *smb_fname_dst)
5726 const char *psrc = smb_fname_src->base_name;
5727 const char *pdst = smb_fname_dst->base_name;
5730 if (psrc[0] == '.' && psrc[1] == '/') {
5733 if (pdst[0] == '.' && pdst[1] == '/') {
5736 if ((slen = strlen(psrc)) > strlen(pdst)) {
5739 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5743 * Do the notify calls from a rename
5746 static void notify_rename(connection_struct *conn, bool is_dir,
5747 const struct smb_filename *smb_fname_src,
5748 const struct smb_filename *smb_fname_dst)
5750 char *parent_dir_src = NULL;
5751 char *parent_dir_dst = NULL;
5752 char *fname_src = NULL;
5753 char *fname_dst = NULL;
5757 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5758 : FILE_NOTIFY_CHANGE_FILE_NAME;
5760 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5761 &parent_dir_src, NULL) ||
5762 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5763 &parent_dir_dst, NULL)) {
5767 status = get_full_smb_filename(talloc_tos(), smb_fname_src,
5769 if (!NT_STATUS_IS_OK(status)) {
5772 status = get_full_smb_filename(talloc_tos(), smb_fname_dst,
5774 if (!NT_STATUS_IS_OK(status)) {
5778 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5779 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, fname_src);
5780 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, fname_dst);
5783 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, fname_src);
5784 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, fname_dst);
5787 /* this is a strange one. w2k3 gives an additional event for
5788 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5789 files, but not directories */
5791 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5792 FILE_NOTIFY_CHANGE_ATTRIBUTES
5793 |FILE_NOTIFY_CHANGE_CREATION,
5797 TALLOC_FREE(parent_dir_src);
5798 TALLOC_FREE(parent_dir_dst);
5799 TALLOC_FREE(fname_src);
5800 TALLOC_FREE(fname_dst);
5803 /****************************************************************************
5804 Rename an open file - given an fsp.
5805 ****************************************************************************/
5807 NTSTATUS rename_internals_fsp(connection_struct *conn,
5809 const struct smb_filename *smb_fname_dst_in,
5811 bool replace_if_exists)
5813 TALLOC_CTX *ctx = talloc_tos();
5814 struct smb_filename *smb_fname_src = NULL;
5815 struct smb_filename *smb_fname_dst = NULL;
5816 SMB_STRUCT_STAT sbuf;
5817 NTSTATUS status = NT_STATUS_OK;
5818 struct share_mode_lock *lck = NULL;
5819 bool dst_exists, old_is_stream, new_is_stream;
5823 status = check_name(conn, smb_fname_dst_in->base_name);
5824 if (!NT_STATUS_IS_OK(status)) {
5828 /* Make a copy of the src and dst smb_fname structs */
5829 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5830 if (!NT_STATUS_IS_OK(status)) {
5835 * This will be replaced with copy_smb_filename() when fsp->fsp_name
5836 * is converted to store an smb_filename struct.
5838 status = create_synthetic_smb_fname_split(ctx, fsp->fsp_name, NULL,
5840 if (!NT_STATUS_IS_OK(status)) {
5844 /* Ensure the dst smb_fname contains a '/' */
5845 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5847 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5848 smb_fname_dst->base_name);
5850 status = NT_STATUS_NO_MEMORY;
5853 TALLOC_FREE(smb_fname_dst->base_name);
5854 smb_fname_dst->base_name = tmp;
5858 * Check for special case with case preserving and not
5859 * case sensitive. If the old last component differs from the original
5860 * last component only by case, then we should allow
5861 * the rename (user is trying to change the case of the
5864 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5865 strequal(smb_fname_src->base_name, smb_fname_dst->base_name) &&
5866 strequal(smb_fname_src->stream_name, smb_fname_dst->stream_name)) {
5868 char *fname_dst_lcomp_base_mod = NULL;
5869 struct smb_filename *smb_fname_orig_lcomp = NULL;
5872 * Get the last component of the destination name. Note that
5873 * we guarantee that destination name contains a '/' character
5876 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5877 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5878 if (!fname_dst_lcomp_base_mod) {
5879 status = NT_STATUS_NO_MEMORY;
5884 * Create an smb_filename struct using the original last
5885 * component of the destination.
5887 status = create_synthetic_smb_fname_split(ctx,
5888 smb_fname_dst->original_lcomp, NULL,
5889 &smb_fname_orig_lcomp);
5890 if (!NT_STATUS_IS_OK(status)) {
5891 TALLOC_FREE(fname_dst_lcomp_base_mod);
5895 /* If the base names only differ by case, use original. */
5896 if(!strcsequal(fname_dst_lcomp_base_mod,
5897 smb_fname_orig_lcomp->base_name)) {
5900 * Replace the modified last component with the
5903 *last_slash = '\0'; /* Truncate at the '/' */
5904 tmp = talloc_asprintf(smb_fname_dst,
5906 smb_fname_dst->base_name,
5907 smb_fname_orig_lcomp->base_name);
5909 status = NT_STATUS_NO_MEMORY;
5910 TALLOC_FREE(fname_dst_lcomp_base_mod);
5911 TALLOC_FREE(smb_fname_orig_lcomp);
5914 TALLOC_FREE(smb_fname_dst->base_name);
5915 smb_fname_dst->base_name = tmp;
5918 /* If the stream_names only differ by case, use original. */
5919 if(!strcsequal(smb_fname_dst->stream_name,
5920 smb_fname_orig_lcomp->stream_name)) {
5922 /* Use the original stream. */
5923 tmp = talloc_strdup(smb_fname_dst,
5924 smb_fname_orig_lcomp->stream_name);
5926 status = NT_STATUS_NO_MEMORY;
5927 TALLOC_FREE(fname_dst_lcomp_base_mod);
5928 TALLOC_FREE(smb_fname_orig_lcomp);
5931 TALLOC_FREE(smb_fname_dst->stream_name);
5932 smb_fname_dst->stream_name = tmp;
5934 TALLOC_FREE(fname_dst_lcomp_base_mod);
5935 TALLOC_FREE(smb_fname_orig_lcomp);
5939 * If the src and dest names are identical - including case,
5940 * don't do the rename, just return success.
5943 if (strcsequal(smb_fname_src->base_name, smb_fname_dst->base_name) &&
5944 strcsequal(smb_fname_src->stream_name,
5945 smb_fname_dst->stream_name)) {
5946 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5947 "- returning success\n",
5948 smb_fname_str_dbg(smb_fname_dst)));
5949 status = NT_STATUS_OK;
5953 old_is_stream = is_ntfs_stream_smb_fname(smb_fname_src);
5954 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5956 /* Return the correct error code if both names aren't streams. */
5957 if (!old_is_stream && new_is_stream) {
5958 status = NT_STATUS_OBJECT_NAME_INVALID;
5962 if (old_is_stream && !new_is_stream) {
5963 status = NT_STATUS_INVALID_PARAMETER;
5967 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
5969 if(!replace_if_exists && dst_exists) {
5970 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
5971 "%s -> %s\n", smb_fname_str_dbg(smb_fname_src),
5972 smb_fname_str_dbg(smb_fname_dst)));
5973 status = NT_STATUS_OBJECT_NAME_COLLISION;
5978 struct file_id fileid = vfs_file_id_from_sbuf(conn,
5979 &smb_fname_dst->st);
5980 files_struct *dst_fsp = file_find_di_first(fileid);
5981 /* The file can be open when renaming a stream */
5982 if (dst_fsp && !new_is_stream) {
5983 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5984 status = NT_STATUS_ACCESS_DENIED;
5989 /* Ensure we have a valid stat struct for the source. */
5990 if (fsp->fh->fd != -1) {
5991 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5992 status = map_nt_error_from_unix(errno);
5997 if (fsp->posix_open) {
5998 ret = SMB_VFS_LSTAT(conn, smb_fname_src);
6001 ret = SMB_VFS_STAT(conn, smb_fname_src);
6004 status = map_nt_error_from_unix(errno);
6007 sbuf = smb_fname_src->st;
6010 status = can_rename(conn, fsp, attrs, &sbuf);
6012 if (!NT_STATUS_IS_OK(status)) {
6013 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6014 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6015 smb_fname_str_dbg(smb_fname_dst)));
6016 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6017 status = NT_STATUS_ACCESS_DENIED;
6021 if (rename_path_prefix_equal(smb_fname_src, smb_fname_dst)) {
6022 status = NT_STATUS_ACCESS_DENIED;
6025 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6029 * We have the file open ourselves, so not being able to get the
6030 * corresponding share mode lock is a fatal error.
6033 SMB_ASSERT(lck != NULL);
6035 if(SMB_VFS_RENAME(conn, smb_fname_src, smb_fname_dst) == 0) {
6036 uint32 create_options = fsp->fh->private_options;
6038 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6039 "%s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6040 smb_fname_str_dbg(smb_fname_dst)));
6042 notify_rename(conn, fsp->is_directory, smb_fname_src,
6045 rename_open_files(conn, lck, smb_fname_dst);
6048 * A rename acts as a new file create w.r.t. allowing an initial delete
6049 * on close, probably because in Windows there is a new handle to the
6050 * new file. If initial delete on close was requested but not
6051 * originally set, we need to set it here. This is probably not 100% correct,
6052 * but will work for the CIFSFS client which in non-posix mode
6053 * depends on these semantics. JRA.
6056 if (create_options & FILE_DELETE_ON_CLOSE) {
6057 status = can_set_delete_on_close(fsp, True, 0);
6059 if (NT_STATUS_IS_OK(status)) {
6060 /* Note that here we set the *inital* delete on close flag,
6061 * not the regular one. The magic gets handled in close. */
6062 fsp->initial_delete_on_close = True;
6066 status = NT_STATUS_OK;
6072 if (errno == ENOTDIR || errno == EISDIR) {
6073 status = NT_STATUS_OBJECT_NAME_COLLISION;
6075 status = map_nt_error_from_unix(errno);
6078 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6079 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6080 smb_fname_str_dbg(smb_fname_dst)));
6083 TALLOC_FREE(smb_fname_src);
6084 TALLOC_FREE(smb_fname_dst);
6089 /****************************************************************************
6090 The guts of the rename command, split out so it may be called by the NT SMB
6092 ****************************************************************************/
6094 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6095 connection_struct *conn,
6096 struct smb_request *req,
6097 const char *name_in,
6098 const char *newname_in,
6100 bool replace_if_exists,
6103 uint32_t access_mask)
6105 struct smb_filename *smb_fname_src = NULL;
6106 struct smb_filename *smb_fname_dst = NULL;
6107 char *fname_src_dir = NULL;
6108 char *fname_src_mask = NULL;
6110 NTSTATUS status = NT_STATUS_OK;
6111 struct smb_Dir *dir_hnd = NULL;
6114 int create_options = 0;
6115 bool posix_pathnames = lp_posix_pathnames();
6117 status = unix_convert(ctx, conn, name_in, &smb_fname_src,
6118 src_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6119 if (!NT_STATUS_IS_OK(status)) {
6123 status = unix_convert(ctx, conn, newname_in, &smb_fname_dst,
6125 (dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0)));
6126 if (!NT_STATUS_IS_OK(status)) {
6131 * Split the old name into directory and last component
6132 * strings. Note that unix_convert may have stripped off a
6133 * leading ./ from both name and newname if the rename is
6134 * at the root of the share. We need to make sure either both
6135 * name and newname contain a / character or neither of them do
6136 * as this is checked in resolve_wildcards().
6139 /* Split up the directory from the filename/mask. */
6140 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6141 &fname_src_dir, &fname_src_mask);
6142 if (!NT_STATUS_IS_OK(status)) {
6143 status = NT_STATUS_NO_MEMORY;
6148 * We should only check the mangled cache
6149 * here if unix_convert failed. This means
6150 * that the path in 'mask' doesn't exist
6151 * on the file system and so we need to look
6152 * for a possible mangle. This patch from
6153 * Tine Smukavec <valentin.smukavec@hermes.si>.
6156 if (!VALID_STAT(smb_fname_src->st) &&
6157 mangle_is_mangled(fname_src_mask, conn->params)) {
6158 char *new_mask = NULL;
6159 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6162 TALLOC_FREE(fname_src_mask);
6163 fname_src_mask = new_mask;
6167 if (!src_has_wild) {
6171 * Only one file needs to be renamed. Append the mask back
6172 * onto the directory.
6174 TALLOC_FREE(smb_fname_src->base_name);
6175 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6179 if (!smb_fname_src->base_name) {
6180 status = NT_STATUS_NO_MEMORY;
6184 /* Ensure dst fname contains a '/' also */
6185 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6187 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6188 smb_fname_dst->base_name);
6190 status = NT_STATUS_NO_MEMORY;
6193 TALLOC_FREE(smb_fname_dst->base_name);
6194 smb_fname_dst->base_name = tmp;
6197 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6198 "case_preserve = %d, short case preserve = %d, "
6199 "directory = %s, newname = %s, "
6200 "last_component_dest = %s\n",
6201 conn->case_sensitive, conn->case_preserve,
6202 conn->short_case_preserve,
6203 smb_fname_str_dbg(smb_fname_src),
6204 smb_fname_str_dbg(smb_fname_dst),
6205 smb_fname_dst->original_lcomp));
6207 /* The dest name still may have wildcards. */
6208 if (dest_has_wild) {
6209 char *fname_dst_mod = NULL;
6210 if (!resolve_wildcards(smb_fname_dst,
6211 smb_fname_src->base_name,
6212 smb_fname_dst->base_name,
6214 DEBUG(6, ("rename_internals: resolve_wildcards "
6216 smb_fname_src->base_name,
6217 smb_fname_dst->base_name));
6218 status = NT_STATUS_NO_MEMORY;
6221 TALLOC_FREE(smb_fname_dst->base_name);
6222 smb_fname_dst->base_name = fname_dst_mod;
6225 ZERO_STRUCT(smb_fname_src->st);
6226 if (posix_pathnames) {
6227 SMB_VFS_LSTAT(conn, smb_fname_src);
6229 SMB_VFS_STAT(conn, smb_fname_src);
6232 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6233 create_options |= FILE_DIRECTORY_FILE;
6236 status = SMB_VFS_CREATE_FILE(
6239 0, /* root_dir_fid */
6240 smb_fname_src, /* fname */
6241 access_mask, /* access_mask */
6242 (FILE_SHARE_READ | /* share_access */
6244 FILE_OPEN, /* create_disposition*/
6245 create_options, /* create_options */
6246 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6247 0, /* oplock_request */
6248 0, /* allocation_size */
6254 if (!NT_STATUS_IS_OK(status)) {
6255 DEBUG(3, ("Could not open rename source %s: %s\n",
6256 smb_fname_str_dbg(smb_fname_src),
6257 nt_errstr(status)));
6261 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6262 attrs, replace_if_exists);
6264 close_file(req, fsp, NORMAL_CLOSE);
6266 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6267 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6268 smb_fname_str_dbg(smb_fname_dst)));
6274 * Wildcards - process each file that matches.
6276 if (strequal(fname_src_mask, "????????.???")) {
6277 TALLOC_FREE(fname_src_mask);
6278 fname_src_mask = talloc_strdup(ctx, "*");
6279 if (!fname_src_mask) {
6280 status = NT_STATUS_NO_MEMORY;
6285 status = check_name(conn, fname_src_dir);
6286 if (!NT_STATUS_IS_OK(status)) {
6290 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6292 if (dir_hnd == NULL) {
6293 status = map_nt_error_from_unix(errno);
6297 status = NT_STATUS_NO_SUCH_FILE;
6299 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6300 * - gentest fix. JRA
6303 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
6304 files_struct *fsp = NULL;
6305 char *destname = NULL;
6306 bool sysdir_entry = False;
6308 /* Quick check for "." and ".." */
6309 if (ISDOT(dname) || ISDOTDOT(dname)) {
6311 sysdir_entry = True;
6317 if (!is_visible_file(conn, fname_src_dir, dname,
6318 &smb_fname_src->st, false)) {
6322 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6327 status = NT_STATUS_OBJECT_NAME_INVALID;
6331 TALLOC_FREE(smb_fname_src->base_name);
6332 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6336 if (!smb_fname_src->base_name) {
6337 status = NT_STATUS_NO_MEMORY;
6341 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6342 smb_fname_dst->base_name,
6344 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6345 smb_fname_src->base_name, destname));
6349 status = NT_STATUS_NO_MEMORY;
6353 TALLOC_FREE(smb_fname_dst->base_name);
6354 smb_fname_dst->base_name = destname;
6356 ZERO_STRUCT(smb_fname_src->st);
6357 if (posix_pathnames) {
6358 SMB_VFS_LSTAT(conn, smb_fname_src);
6360 SMB_VFS_STAT(conn, smb_fname_src);
6365 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6366 create_options |= FILE_DIRECTORY_FILE;
6369 status = SMB_VFS_CREATE_FILE(
6372 0, /* root_dir_fid */
6373 smb_fname_src, /* fname */
6374 access_mask, /* access_mask */
6375 (FILE_SHARE_READ | /* share_access */
6377 FILE_OPEN, /* create_disposition*/
6378 create_options, /* create_options */
6379 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6380 0, /* oplock_request */
6381 0, /* allocation_size */
6387 if (!NT_STATUS_IS_OK(status)) {
6388 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6389 "returned %s rename %s -> %s\n",
6391 smb_fname_str_dbg(smb_fname_src),
6392 smb_fname_str_dbg(smb_fname_dst)));
6396 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6398 if (!smb_fname_dst->original_lcomp) {
6399 status = NT_STATUS_NO_MEMORY;
6403 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6404 attrs, replace_if_exists);
6406 close_file(req, fsp, NORMAL_CLOSE);
6408 if (!NT_STATUS_IS_OK(status)) {
6409 DEBUG(3, ("rename_internals_fsp returned %s for "
6410 "rename %s -> %s\n", nt_errstr(status),
6411 smb_fname_str_dbg(smb_fname_src),
6412 smb_fname_str_dbg(smb_fname_dst)));
6418 DEBUG(3,("rename_internals: doing rename on %s -> "
6419 "%s\n", smb_fname_str_dbg(smb_fname_src),
6420 smb_fname_str_dbg(smb_fname_src)));
6423 TALLOC_FREE(dir_hnd);
6425 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6426 status = map_nt_error_from_unix(errno);
6430 TALLOC_FREE(smb_fname_src);
6431 TALLOC_FREE(smb_fname_dst);
6432 TALLOC_FREE(fname_src_dir);
6433 TALLOC_FREE(fname_src_mask);
6437 /****************************************************************************
6439 ****************************************************************************/
6441 void reply_mv(struct smb_request *req)
6443 connection_struct *conn = req->conn;
6445 char *newname = NULL;
6449 bool src_has_wcard = False;
6450 bool dest_has_wcard = False;
6451 TALLOC_CTX *ctx = talloc_tos();
6453 START_PROFILE(SMBmv);
6456 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6461 attrs = SVAL(req->vwv+0, 0);
6463 p = (const char *)req->buf + 1;
6464 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6465 &status, &src_has_wcard);
6466 if (!NT_STATUS_IS_OK(status)) {
6467 reply_nterror(req, status);
6472 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6473 &status, &dest_has_wcard);
6474 if (!NT_STATUS_IS_OK(status)) {
6475 reply_nterror(req, status);
6480 status = resolve_dfspath_wcard(ctx, conn,
6481 req->flags2 & FLAGS2_DFS_PATHNAMES,
6485 if (!NT_STATUS_IS_OK(status)) {
6486 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6487 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6488 ERRSRV, ERRbadpath);
6492 reply_nterror(req, status);
6497 status = resolve_dfspath_wcard(ctx, conn,
6498 req->flags2 & FLAGS2_DFS_PATHNAMES,
6502 if (!NT_STATUS_IS_OK(status)) {
6503 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6504 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6505 ERRSRV, ERRbadpath);
6509 reply_nterror(req, status);
6514 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6516 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6517 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6518 if (!NT_STATUS_IS_OK(status)) {
6519 if (open_was_deferred(req->mid)) {
6520 /* We have re-scheduled this call. */
6524 reply_nterror(req, status);
6529 reply_outbuf(req, 0, 0);
6535 /*******************************************************************
6536 Copy a file as part of a reply_copy.
6537 ******************************************************************/
6540 * TODO: check error codes on all callers
6543 NTSTATUS copy_file(TALLOC_CTX *ctx,
6544 connection_struct *conn,
6545 struct smb_filename *smb_fname_src,
6546 struct smb_filename *smb_fname_dst,
6549 bool target_is_directory)
6551 struct smb_filename *smb_fname_dst_tmp = NULL;
6552 char *fname_src = NULL;
6554 files_struct *fsp1,*fsp2;
6556 uint32 new_create_disposition;
6560 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6561 if (!NT_STATUS_IS_OK(status)) {
6566 * If the target is a directory, extract the last component from the
6567 * src filename and append it to the dst filename
6569 if (target_is_directory) {
6572 /* dest/target can't be a stream if it's a directory. */
6573 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6575 p = strrchr_m(smb_fname_src->base_name,'/');
6579 p = smb_fname_src->base_name;
6581 smb_fname_dst_tmp->base_name =
6582 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6584 if (!smb_fname_dst_tmp->base_name) {
6585 status = NT_STATUS_NO_MEMORY;
6590 status = vfs_file_exist(conn, smb_fname_src);
6591 if (!NT_STATUS_IS_OK(status)) {
6595 if (!target_is_directory && count) {
6596 new_create_disposition = FILE_OPEN;
6598 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6599 0, ofun, NULL, NULL,
6600 &new_create_disposition,
6602 status = NT_STATUS_INVALID_PARAMETER;
6607 /* Open the src file for reading. */
6608 status = SMB_VFS_CREATE_FILE(
6611 0, /* root_dir_fid */
6612 smb_fname_src, /* fname */
6613 FILE_GENERIC_READ, /* access_mask */
6614 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6615 FILE_OPEN, /* create_disposition*/
6616 0, /* create_options */
6617 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6618 INTERNAL_OPEN_ONLY, /* oplock_request */
6619 0, /* allocation_size */
6625 if (!NT_STATUS_IS_OK(status)) {
6629 status = get_full_smb_filename(talloc_tos(), smb_fname_src, &fname_src);
6630 if (!NT_STATUS_IS_OK(status)) {
6634 dosattrs = dos_mode(conn, fname_src, &smb_fname_src->st);
6636 TALLOC_FREE(fname_src);
6638 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6639 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6642 /* Open the dst file for writing. */
6643 status = SMB_VFS_CREATE_FILE(
6646 0, /* root_dir_fid */
6647 smb_fname_dst, /* fname */
6648 FILE_GENERIC_WRITE, /* access_mask */
6649 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6650 new_create_disposition, /* create_disposition*/
6651 0, /* create_options */
6652 dosattrs, /* file_attributes */
6653 INTERNAL_OPEN_ONLY, /* oplock_request */
6654 0, /* allocation_size */
6660 if (!NT_STATUS_IS_OK(status)) {
6661 close_file(NULL, fsp1, ERROR_CLOSE);
6665 if ((ofun&3) == 1) {
6666 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6667 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6669 * Stop the copy from occurring.
6672 smb_fname_src->st.st_ex_size = 0;
6676 /* Do the actual copy. */
6677 if (smb_fname_src->st.st_ex_size) {
6678 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6681 close_file(NULL, fsp1, NORMAL_CLOSE);
6683 /* Ensure the modtime is set correctly on the destination file. */
6684 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6687 * As we are opening fsp1 read-only we only expect
6688 * an error on close on fsp2 if we are out of space.
6689 * Thus we don't look at the error return from the
6692 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6694 if (!NT_STATUS_IS_OK(status)) {
6698 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6699 status = NT_STATUS_DISK_FULL;
6703 status = NT_STATUS_OK;
6706 TALLOC_FREE(smb_fname_dst_tmp);
6710 /****************************************************************************
6711 Reply to a file copy.
6712 ****************************************************************************/
6714 void reply_copy(struct smb_request *req)
6716 connection_struct *conn = req->conn;
6717 struct smb_filename *smb_fname_src = NULL;
6718 struct smb_filename *smb_fname_dst = NULL;
6719 char *fname_src = NULL;
6720 char *fname_dst = NULL;
6721 char *fname_src_mask = NULL;
6722 char *fname_src_dir = NULL;
6725 int error = ERRnoaccess;
6730 bool target_is_directory=False;
6731 bool source_has_wild = False;
6732 bool dest_has_wild = False;
6734 TALLOC_CTX *ctx = talloc_tos();
6736 START_PROFILE(SMBcopy);
6739 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6743 tid2 = SVAL(req->vwv+0, 0);
6744 ofun = SVAL(req->vwv+1, 0);
6745 flags = SVAL(req->vwv+2, 0);
6747 p = (const char *)req->buf;
6748 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6749 &status, &source_has_wild);
6750 if (!NT_STATUS_IS_OK(status)) {
6751 reply_nterror(req, status);
6754 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6755 &status, &dest_has_wild);
6756 if (!NT_STATUS_IS_OK(status)) {
6757 reply_nterror(req, status);
6761 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6763 if (tid2 != conn->cnum) {
6764 /* can't currently handle inter share copies XXXX */
6765 DEBUG(3,("Rejecting inter-share copy\n"));
6766 reply_doserror(req, ERRSRV, ERRinvdevice);
6770 status = resolve_dfspath_wcard(ctx, conn,
6771 req->flags2 & FLAGS2_DFS_PATHNAMES,
6775 if (!NT_STATUS_IS_OK(status)) {
6776 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6777 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6778 ERRSRV, ERRbadpath);
6781 reply_nterror(req, status);
6785 status = resolve_dfspath_wcard(ctx, conn,
6786 req->flags2 & FLAGS2_DFS_PATHNAMES,
6790 if (!NT_STATUS_IS_OK(status)) {
6791 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6792 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6793 ERRSRV, ERRbadpath);
6796 reply_nterror(req, status);
6800 status = unix_convert(ctx, conn, fname_src, &smb_fname_src,
6801 source_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6802 if (!NT_STATUS_IS_OK(status)) {
6803 reply_nterror(req, status);
6807 status = unix_convert(ctx, conn, fname_dst, &smb_fname_dst,
6808 dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6809 if (!NT_STATUS_IS_OK(status)) {
6810 reply_nterror(req, status);
6814 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6816 if ((flags&1) && target_is_directory) {
6817 reply_doserror(req, ERRDOS, ERRbadfile);
6821 if ((flags&2) && !target_is_directory) {
6822 reply_doserror(req, ERRDOS, ERRbadpath);
6826 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6827 /* wants a tree copy! XXXX */
6828 DEBUG(3,("Rejecting tree copy\n"));
6829 reply_doserror(req, ERRSRV, ERRerror);
6833 /* Split up the directory from the filename/mask. */
6834 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6835 &fname_src_dir, &fname_src_mask);
6836 if (!NT_STATUS_IS_OK(status)) {
6837 reply_nterror(req, NT_STATUS_NO_MEMORY);
6842 * We should only check the mangled cache
6843 * here if unix_convert failed. This means
6844 * that the path in 'mask' doesn't exist
6845 * on the file system and so we need to look
6846 * for a possible mangle. This patch from
6847 * Tine Smukavec <valentin.smukavec@hermes.si>.
6849 if (!VALID_STAT(smb_fname_src->st) &&
6850 mangle_is_mangled(fname_src_mask, conn->params)) {
6851 char *new_mask = NULL;
6852 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6853 &new_mask, conn->params);
6855 /* Use demangled name if one was successfully found. */
6857 TALLOC_FREE(fname_src_mask);
6858 fname_src_mask = new_mask;
6862 if (!source_has_wild) {
6865 * Only one file needs to be copied. Append the mask back onto
6868 TALLOC_FREE(smb_fname_src->base_name);
6869 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6873 if (!smb_fname_src->base_name) {
6874 reply_nterror(req, NT_STATUS_NO_MEMORY);
6878 if (dest_has_wild) {
6879 char *fname_dst_mod = NULL;
6880 if (!resolve_wildcards(smb_fname_dst,
6881 smb_fname_src->base_name,
6882 smb_fname_dst->base_name,
6884 reply_nterror(req, NT_STATUS_NO_MEMORY);
6887 TALLOC_FREE(smb_fname_dst->base_name);
6888 smb_fname_dst->base_name = fname_dst_mod;
6891 status = check_name(conn, smb_fname_src->base_name);
6892 if (!NT_STATUS_IS_OK(status)) {
6893 reply_nterror(req, status);
6897 status = check_name(conn, smb_fname_dst->base_name);
6898 if (!NT_STATUS_IS_OK(status)) {
6899 reply_nterror(req, status);
6903 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6904 ofun, count, target_is_directory);
6906 if(!NT_STATUS_IS_OK(status)) {
6907 reply_nterror(req, status);
6913 struct smb_Dir *dir_hnd = NULL;
6914 const char *dname = NULL;
6918 * There is a wildcard that requires us to actually read the
6919 * src dir and copy each file matching the mask to the dst.
6920 * Right now streams won't be copied, but this could
6921 * presumably be added with a nested loop for reach dir entry.
6923 SMB_ASSERT(!smb_fname_src->stream_name);
6924 SMB_ASSERT(!smb_fname_dst->stream_name);
6926 smb_fname_src->stream_name = NULL;
6927 smb_fname_dst->stream_name = NULL;
6929 if (strequal(fname_src_mask,"????????.???")) {
6930 TALLOC_FREE(fname_src_mask);
6931 fname_src_mask = talloc_strdup(ctx, "*");
6932 if (!fname_src_mask) {
6933 reply_nterror(req, NT_STATUS_NO_MEMORY);
6938 status = check_name(conn, fname_src_dir);
6939 if (!NT_STATUS_IS_OK(status)) {
6940 reply_nterror(req, status);
6944 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6945 if (dir_hnd == NULL) {
6946 status = map_nt_error_from_unix(errno);
6947 reply_nterror(req, status);
6953 /* Iterate over the src dir copying each entry to the dst. */
6954 while ((dname = ReadDirName(dir_hnd, &offset,
6955 &smb_fname_src->st))) {
6956 char *destname = NULL;
6958 if (ISDOT(dname) || ISDOTDOT(dname)) {
6962 if (!is_visible_file(conn, fname_src_dir, dname,
6963 &smb_fname_src->st, false)) {
6967 if(!mask_match(dname, fname_src_mask,
6968 conn->case_sensitive)) {
6972 error = ERRnoaccess;
6974 /* Get the src smb_fname struct setup. */
6975 TALLOC_FREE(smb_fname_src->base_name);
6976 smb_fname_src->base_name =
6977 talloc_asprintf(smb_fname_src, "%s/%s",
6978 fname_src_dir, dname);
6980 if (!smb_fname_src->base_name) {
6981 TALLOC_FREE(dir_hnd);
6982 reply_nterror(req, NT_STATUS_NO_MEMORY);
6986 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6987 smb_fname_dst->base_name,
6992 TALLOC_FREE(dir_hnd);
6993 reply_nterror(req, NT_STATUS_NO_MEMORY);
6997 TALLOC_FREE(smb_fname_dst->base_name);
6998 smb_fname_dst->base_name = destname;
7000 status = check_name(conn, smb_fname_src->base_name);
7001 if (!NT_STATUS_IS_OK(status)) {
7002 TALLOC_FREE(dir_hnd);
7003 reply_nterror(req, status);
7007 status = check_name(conn, smb_fname_dst->base_name);
7008 if (!NT_STATUS_IS_OK(status)) {
7009 TALLOC_FREE(dir_hnd);
7010 reply_nterror(req, status);
7014 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7015 smb_fname_src->base_name,
7016 smb_fname_dst->base_name));
7018 status = copy_file(ctx, conn, smb_fname_src,
7019 smb_fname_dst, ofun, count,
7020 target_is_directory);
7021 if (NT_STATUS_IS_OK(status)) {
7025 TALLOC_FREE(dir_hnd);
7030 /* Error on close... */
7032 reply_unixerror(req, ERRHRD, ERRgeneral);
7036 reply_doserror(req, ERRDOS, error);
7040 reply_outbuf(req, 1, 0);
7041 SSVAL(req->outbuf,smb_vwv0,count);
7043 TALLOC_FREE(smb_fname_src);
7044 TALLOC_FREE(smb_fname_dst);
7045 TALLOC_FREE(fname_src);
7046 TALLOC_FREE(fname_dst);
7047 TALLOC_FREE(fname_src_mask);
7048 TALLOC_FREE(fname_src_dir);
7050 END_PROFILE(SMBcopy);
7055 #define DBGC_CLASS DBGC_LOCKING
7057 /****************************************************************************
7058 Get a lock pid, dealing with large count requests.
7059 ****************************************************************************/
7061 uint32 get_lock_pid(const uint8_t *data, int data_offset,
7062 bool large_file_format)
7064 if(!large_file_format)
7065 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
7067 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7070 /****************************************************************************
7071 Get a lock count, dealing with large count requests.
7072 ****************************************************************************/
7074 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7075 bool large_file_format)
7079 if(!large_file_format) {
7080 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7083 #if defined(HAVE_LONGLONG)
7084 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7085 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7086 #else /* HAVE_LONGLONG */
7089 * NT4.x seems to be broken in that it sends large file (64 bit)
7090 * lockingX calls even if the CAP_LARGE_FILES was *not*
7091 * negotiated. For boxes without large unsigned ints truncate the
7092 * lock count by dropping the top 32 bits.
7095 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7096 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7097 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7098 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7099 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7102 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7103 #endif /* HAVE_LONGLONG */
7109 #if !defined(HAVE_LONGLONG)
7110 /****************************************************************************
7111 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7112 ****************************************************************************/
7114 static uint32 map_lock_offset(uint32 high, uint32 low)
7118 uint32 highcopy = high;
7121 * Try and find out how many significant bits there are in high.
7124 for(i = 0; highcopy; i++)
7128 * We use 31 bits not 32 here as POSIX
7129 * lock offsets may not be negative.
7132 mask = (~0) << (31 - i);
7135 return 0; /* Fail. */
7141 #endif /* !defined(HAVE_LONGLONG) */
7143 /****************************************************************************
7144 Get a lock offset, dealing with large offset requests.
7145 ****************************************************************************/
7147 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7148 bool large_file_format, bool *err)
7150 uint64_t offset = 0;
7154 if(!large_file_format) {
7155 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7158 #if defined(HAVE_LONGLONG)
7159 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7160 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7161 #else /* HAVE_LONGLONG */
7164 * NT4.x seems to be broken in that it sends large file (64 bit)
7165 * lockingX calls even if the CAP_LARGE_FILES was *not*
7166 * negotiated. For boxes without large unsigned ints mangle the
7167 * lock offset by mapping the top 32 bits onto the lower 32.
7170 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7171 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7172 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7175 if((new_low = map_lock_offset(high, low)) == 0) {
7177 return (uint64_t)-1;
7180 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7181 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7182 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7183 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7186 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7187 #endif /* HAVE_LONGLONG */
7193 /****************************************************************************
7194 Reply to a lockingX request.
7195 ****************************************************************************/
7197 void reply_lockingX(struct smb_request *req)
7199 connection_struct *conn = req->conn;
7201 unsigned char locktype;
7202 unsigned char oplocklevel;
7205 uint64_t count = 0, offset = 0;
7209 const uint8_t *data;
7210 bool large_file_format;
7212 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7214 START_PROFILE(SMBlockingX);
7217 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7218 END_PROFILE(SMBlockingX);
7222 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7223 locktype = CVAL(req->vwv+3, 0);
7224 oplocklevel = CVAL(req->vwv+3, 1);
7225 num_ulocks = SVAL(req->vwv+6, 0);
7226 num_locks = SVAL(req->vwv+7, 0);
7227 lock_timeout = IVAL(req->vwv+4, 0);
7228 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7230 if (!check_fsp(conn, req, fsp)) {
7231 END_PROFILE(SMBlockingX);
7237 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7238 /* we don't support these - and CANCEL_LOCK makes w2k
7239 and XP reboot so I don't really want to be
7240 compatible! (tridge) */
7241 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7242 END_PROFILE(SMBlockingX);
7246 /* Check if this is an oplock break on a file
7247 we have granted an oplock on.
7249 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7250 /* Client can insist on breaking to none. */
7251 bool break_to_none = (oplocklevel == 0);
7254 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7255 "for fnum = %d\n", (unsigned int)oplocklevel,
7259 * Make sure we have granted an exclusive or batch oplock on
7263 if (fsp->oplock_type == 0) {
7265 /* The Samba4 nbench simulator doesn't understand
7266 the difference between break to level2 and break
7267 to none from level2 - it sends oplock break
7268 replies in both cases. Don't keep logging an error
7269 message here - just ignore it. JRA. */
7271 DEBUG(5,("reply_lockingX: Error : oplock break from "
7272 "client for fnum = %d (oplock=%d) and no "
7273 "oplock granted on this file (%s).\n",
7274 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
7276 /* if this is a pure oplock break request then don't
7278 if (num_locks == 0 && num_ulocks == 0) {
7279 END_PROFILE(SMBlockingX);
7282 END_PROFILE(SMBlockingX);
7283 reply_doserror(req, ERRDOS, ERRlock);
7288 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7290 result = remove_oplock(fsp);
7292 result = downgrade_oplock(fsp);
7296 DEBUG(0, ("reply_lockingX: error in removing "
7297 "oplock on file %s\n", fsp->fsp_name));
7298 /* Hmmm. Is this panic justified? */
7299 smb_panic("internal tdb error");
7302 reply_to_oplock_break_requests(fsp);
7304 /* if this is a pure oplock break request then don't send a
7306 if (num_locks == 0 && num_ulocks == 0) {
7307 /* Sanity check - ensure a pure oplock break is not a
7309 if(CVAL(req->vwv+0, 0) != 0xff)
7310 DEBUG(0,("reply_lockingX: Error : pure oplock "
7311 "break is a chained %d request !\n",
7312 (unsigned int)CVAL(req->vwv+0, 0)));
7313 END_PROFILE(SMBlockingX);
7319 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7320 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7321 END_PROFILE(SMBlockingX);
7325 /* Data now points at the beginning of the list
7326 of smb_unlkrng structs */
7327 for(i = 0; i < (int)num_ulocks; i++) {
7328 lock_pid = get_lock_pid( data, i, large_file_format);
7329 count = get_lock_count( data, i, large_file_format);
7330 offset = get_lock_offset( data, i, large_file_format, &err);
7333 * There is no error code marked "stupid client bug".... :-).
7336 END_PROFILE(SMBlockingX);
7337 reply_doserror(req, ERRDOS, ERRnoaccess);
7341 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
7342 "pid %u, file %s\n", (double)offset, (double)count,
7343 (unsigned int)lock_pid, fsp->fsp_name ));
7345 status = do_unlock(smbd_messaging_context(),
7352 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
7353 nt_errstr(status)));
7355 if (NT_STATUS_V(status)) {
7356 END_PROFILE(SMBlockingX);
7357 reply_nterror(req, status);
7362 /* Setup the timeout in seconds. */
7364 if (!lp_blocking_locks(SNUM(conn))) {
7368 /* Now do any requested locks */
7369 data += ((large_file_format ? 20 : 10)*num_ulocks);
7371 /* Data now points at the beginning of the list
7372 of smb_lkrng structs */
7374 for(i = 0; i < (int)num_locks; i++) {
7375 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
7376 READ_LOCK:WRITE_LOCK);
7377 lock_pid = get_lock_pid( data, i, large_file_format);
7378 count = get_lock_count( data, i, large_file_format);
7379 offset = get_lock_offset( data, i, large_file_format, &err);
7382 * There is no error code marked "stupid client bug".... :-).
7385 END_PROFILE(SMBlockingX);
7386 reply_doserror(req, ERRDOS, ERRnoaccess);
7390 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
7391 "%u, file %s timeout = %d\n", (double)offset,
7392 (double)count, (unsigned int)lock_pid,
7393 fsp->fsp_name, (int)lock_timeout ));
7395 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7396 struct blocking_lock_record *blr = NULL;
7398 if (lp_blocking_locks(SNUM(conn))) {
7400 /* Schedule a message to ourselves to
7401 remove the blocking lock record and
7402 return the right error. */
7404 blr = blocking_lock_cancel(fsp,
7410 NT_STATUS_FILE_LOCK_CONFLICT);
7412 END_PROFILE(SMBlockingX);
7417 ERRcancelviolation));
7421 /* Remove a matching pending lock. */
7422 status = do_lock_cancel(fsp,
7429 bool blocking_lock = lock_timeout ? True : False;
7430 bool defer_lock = False;
7431 struct byte_range_lock *br_lck;
7432 uint32 block_smbpid;
7434 br_lck = do_lock(smbd_messaging_context(),
7446 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7447 /* Windows internal resolution for blocking locks seems
7448 to be about 200ms... Don't wait for less than that. JRA. */
7449 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7450 lock_timeout = lp_lock_spin_time();
7455 /* This heuristic seems to match W2K3 very well. If a
7456 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7457 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7458 far as I can tell. Replacement for do_lock_spin(). JRA. */
7460 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7461 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7463 lock_timeout = lp_lock_spin_time();
7466 if (br_lck && defer_lock) {
7468 * A blocking lock was requested. Package up
7469 * this smb into a queued request and push it
7470 * onto the blocking lock queue.
7472 if(push_blocking_lock_request(br_lck,
7483 TALLOC_FREE(br_lck);
7484 END_PROFILE(SMBlockingX);
7489 TALLOC_FREE(br_lck);
7492 if (NT_STATUS_V(status)) {
7493 END_PROFILE(SMBlockingX);
7494 reply_nterror(req, status);
7499 /* If any of the above locks failed, then we must unlock
7500 all of the previous locks (X/Open spec). */
7502 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7506 * Ensure we don't do a remove on the lock that just failed,
7507 * as under POSIX rules, if we have a lock already there, we
7508 * will delete it (and we shouldn't) .....
7510 for(i--; i >= 0; i--) {
7511 lock_pid = get_lock_pid( data, i, large_file_format);
7512 count = get_lock_count( data, i, large_file_format);
7513 offset = get_lock_offset( data, i, large_file_format,
7517 * There is no error code marked "stupid client
7521 END_PROFILE(SMBlockingX);
7522 reply_doserror(req, ERRDOS, ERRnoaccess);
7526 do_unlock(smbd_messaging_context(),
7533 END_PROFILE(SMBlockingX);
7534 reply_nterror(req, status);
7538 reply_outbuf(req, 2, 0);
7540 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7541 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7543 END_PROFILE(SMBlockingX);
7548 #define DBGC_CLASS DBGC_ALL
7550 /****************************************************************************
7551 Reply to a SMBreadbmpx (read block multiplex) request.
7552 Always reply with an error, if someone has a platform really needs this,
7553 please contact vl@samba.org
7554 ****************************************************************************/
7556 void reply_readbmpx(struct smb_request *req)
7558 START_PROFILE(SMBreadBmpx);
7559 reply_doserror(req, ERRSRV, ERRuseSTD);
7560 END_PROFILE(SMBreadBmpx);
7564 /****************************************************************************
7565 Reply to a SMBreadbs (read block multiplex secondary) request.
7566 Always reply with an error, if someone has a platform really needs this,
7567 please contact vl@samba.org
7568 ****************************************************************************/
7570 void reply_readbs(struct smb_request *req)
7572 START_PROFILE(SMBreadBs);
7573 reply_doserror(req, ERRSRV, ERRuseSTD);
7574 END_PROFILE(SMBreadBs);
7578 /****************************************************************************
7579 Reply to a SMBsetattrE.
7580 ****************************************************************************/
7582 void reply_setattrE(struct smb_request *req)
7584 connection_struct *conn = req->conn;
7585 struct smb_file_time ft;
7587 SMB_STRUCT_STAT sbuf;
7590 START_PROFILE(SMBsetattrE);
7594 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7595 END_PROFILE(SMBsetattrE);
7599 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7601 if(!fsp || (fsp->conn != conn)) {
7602 reply_doserror(req, ERRDOS, ERRbadfid);
7603 END_PROFILE(SMBsetattrE);
7609 * Convert the DOS times into unix times.
7612 ft.atime = convert_time_t_to_timespec(
7613 srv_make_unix_date2(req->vwv+3));
7614 ft.mtime = convert_time_t_to_timespec(
7615 srv_make_unix_date2(req->vwv+5));
7616 ft.create_time = convert_time_t_to_timespec(
7617 srv_make_unix_date2(req->vwv+1));
7619 reply_outbuf(req, 0, 0);
7622 * Patch from Ray Frush <frush@engr.colostate.edu>
7623 * Sometimes times are sent as zero - ignore them.
7626 /* Ensure we have a valid stat struct for the source. */
7627 if (fsp->fh->fd != -1) {
7628 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7629 status = map_nt_error_from_unix(errno);
7630 reply_nterror(req, status);
7631 END_PROFILE(SMBsetattrE);
7637 if (fsp->posix_open) {
7638 ret = vfs_lstat_smb_fname(conn, fsp->fsp_name, &sbuf);
7640 ret = vfs_stat_smb_fname(conn, fsp->fsp_name, &sbuf);
7643 status = map_nt_error_from_unix(errno);
7644 reply_nterror(req, status);
7645 END_PROFILE(SMBsetattrE);
7650 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7652 if (!NT_STATUS_IS_OK(status)) {
7653 reply_doserror(req, ERRDOS, ERRnoaccess);
7654 END_PROFILE(SMBsetattrE);
7658 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7661 (unsigned int)ft.atime.tv_sec,
7662 (unsigned int)ft.mtime.tv_sec,
7663 (unsigned int)ft.create_time.tv_sec
7666 END_PROFILE(SMBsetattrE);
7671 /* Back from the dead for OS/2..... JRA. */
7673 /****************************************************************************
7674 Reply to a SMBwritebmpx (write block multiplex primary) request.
7675 Always reply with an error, if someone has a platform really needs this,
7676 please contact vl@samba.org
7677 ****************************************************************************/
7679 void reply_writebmpx(struct smb_request *req)
7681 START_PROFILE(SMBwriteBmpx);
7682 reply_doserror(req, ERRSRV, ERRuseSTD);
7683 END_PROFILE(SMBwriteBmpx);
7687 /****************************************************************************
7688 Reply to a SMBwritebs (write block multiplex secondary) request.
7689 Always reply with an error, if someone has a platform really needs this,
7690 please contact vl@samba.org
7691 ****************************************************************************/
7693 void reply_writebs(struct smb_request *req)
7695 START_PROFILE(SMBwriteBs);
7696 reply_doserror(req, ERRSRV, ERRuseSTD);
7697 END_PROFILE(SMBwriteBs);
7701 /****************************************************************************
7702 Reply to a SMBgetattrE.
7703 ****************************************************************************/
7705 void reply_getattrE(struct smb_request *req)
7707 connection_struct *conn = req->conn;
7708 SMB_STRUCT_STAT sbuf;
7711 struct timespec create_ts;
7713 START_PROFILE(SMBgetattrE);
7716 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7717 END_PROFILE(SMBgetattrE);
7721 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7723 if(!fsp || (fsp->conn != conn)) {
7724 reply_doserror(req, ERRDOS, ERRbadfid);
7725 END_PROFILE(SMBgetattrE);
7729 /* Do an fstat on this file */
7730 if(fsp_stat(fsp, &sbuf)) {
7731 reply_unixerror(req, ERRDOS, ERRnoaccess);
7732 END_PROFILE(SMBgetattrE);
7736 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7739 * Convert the times into dos times. Set create
7740 * date to be last modify date as UNIX doesn't save
7744 reply_outbuf(req, 11, 0);
7746 create_ts = sbuf.st_ex_btime;
7747 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7748 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7749 convert_timespec_to_time_t(sbuf.st_ex_atime));
7750 /* Should we check pending modtime here ? JRA */
7751 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7752 convert_timespec_to_time_t(sbuf.st_ex_mtime));
7755 SIVAL(req->outbuf, smb_vwv6, 0);
7756 SIVAL(req->outbuf, smb_vwv8, 0);
7758 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7759 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_ex_size);
7760 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7762 SSVAL(req->outbuf,smb_vwv10, mode);
7764 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7766 END_PROFILE(SMBgetattrE);