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 status = resolve_dfspath(ctx, conn,
991 req->flags2 & FLAGS2_DFS_PATHNAMES,
994 if (!NT_STATUS_IS_OK(status)) {
995 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
996 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
998 END_PROFILE(SMBcheckpath);
1004 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1006 status = unix_convert(ctx, conn, name, &smb_fname, 0);
1007 if (!NT_STATUS_IS_OK(status)) {
1011 status = get_full_smb_filename(ctx, smb_fname, &name);
1012 if (!NT_STATUS_IS_OK(status)) {
1016 status = check_name(conn, name);
1017 if (!NT_STATUS_IS_OK(status)) {
1018 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
1022 if (!VALID_STAT(smb_fname->st) &&
1023 (SMB_VFS_STAT(conn, name, &smb_fname->st) != 0)) {
1024 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
1025 status = map_nt_error_from_unix(errno);
1029 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1030 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1031 ERRDOS, ERRbadpath);
1035 reply_outbuf(req, 0, 0);
1037 TALLOC_FREE(smb_fname);
1038 END_PROFILE(SMBcheckpath);
1043 TALLOC_FREE(smb_fname);
1045 END_PROFILE(SMBcheckpath);
1047 /* We special case this - as when a Windows machine
1048 is parsing a path is steps through the components
1049 one at a time - if a component fails it expects
1050 ERRbadpath, not ERRbadfile.
1052 status = map_checkpath_error(req->flags2, status);
1053 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1055 * Windows returns different error codes if
1056 * the parent directory is valid but not the
1057 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1058 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1059 * if the path is invalid.
1061 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1062 ERRDOS, ERRbadpath);
1066 reply_nterror(req, status);
1069 /****************************************************************************
1071 ****************************************************************************/
1073 void reply_getatr(struct smb_request *req)
1075 connection_struct *conn = req->conn;
1076 struct smb_filename *smb_fname = NULL;
1083 TALLOC_CTX *ctx = talloc_tos();
1085 START_PROFILE(SMBgetatr);
1087 p = (const char *)req->buf + 1;
1088 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1089 if (!NT_STATUS_IS_OK(status)) {
1090 reply_nterror(req, status);
1094 status = resolve_dfspath(ctx, conn,
1095 req->flags2 & FLAGS2_DFS_PATHNAMES,
1098 if (!NT_STATUS_IS_OK(status)) {
1099 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1100 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1101 ERRSRV, ERRbadpath);
1104 reply_nterror(req, status);
1108 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1109 under WfWg - weird! */
1110 if (*fname == '\0') {
1111 mode = aHIDDEN | aDIR;
1112 if (!CAN_WRITE(conn)) {
1118 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1119 if (!NT_STATUS_IS_OK(status)) {
1120 reply_nterror(req, status);
1123 status = get_full_smb_filename(ctx, smb_fname, &fname);
1124 if (!NT_STATUS_IS_OK(status)) {
1125 reply_nterror(req, status);
1128 status = check_name(conn, fname);
1129 if (!NT_STATUS_IS_OK(status)) {
1130 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1131 reply_nterror(req, status);
1134 if (!VALID_STAT(smb_fname->st) &&
1135 (SMB_VFS_STAT(conn, fname, &smb_fname->st) != 0)) {
1136 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1137 reply_unixerror(req, ERRDOS,ERRbadfile);
1141 mode = dos_mode(conn, fname, &smb_fname->st);
1142 size = smb_fname->st.st_ex_size;
1143 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1149 reply_outbuf(req, 10, 0);
1151 SSVAL(req->outbuf,smb_vwv0,mode);
1152 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1153 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1155 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1157 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1159 if (Protocol >= PROTOCOL_NT1) {
1160 SSVAL(req->outbuf, smb_flg2,
1161 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1164 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1167 TALLOC_FREE(smb_fname);
1168 END_PROFILE(SMBgetatr);
1172 /****************************************************************************
1174 ****************************************************************************/
1176 void reply_setatr(struct smb_request *req)
1178 struct smb_file_time ft;
1179 connection_struct *conn = req->conn;
1180 struct smb_filename *smb_fname = NULL;
1186 TALLOC_CTX *ctx = talloc_tos();
1188 START_PROFILE(SMBsetatr);
1193 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1197 p = (const char *)req->buf + 1;
1198 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1199 if (!NT_STATUS_IS_OK(status)) {
1200 reply_nterror(req, status);
1204 status = resolve_dfspath(ctx, conn,
1205 req->flags2 & FLAGS2_DFS_PATHNAMES,
1208 if (!NT_STATUS_IS_OK(status)) {
1209 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1210 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1211 ERRSRV, ERRbadpath);
1214 reply_nterror(req, status);
1218 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1219 if (!NT_STATUS_IS_OK(status)) {
1220 reply_nterror(req, status);
1224 status = get_full_smb_filename(ctx, smb_fname, &fname);
1225 if (!NT_STATUS_IS_OK(status)) {
1226 reply_nterror(req, status);
1230 status = check_name(conn, fname);
1231 if (!NT_STATUS_IS_OK(status)) {
1232 reply_nterror(req, status);
1236 if (fname[0] == '.' && fname[1] == '\0') {
1238 * Not sure here is the right place to catch this
1239 * condition. Might be moved to somewhere else later -- vl
1241 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1245 mode = SVAL(req->vwv+0, 0);
1246 mtime = srv_make_unix_date3(req->vwv+1);
1248 ft.mtime = convert_time_t_to_timespec(mtime);
1249 status = smb_set_file_time(conn, NULL, fname,
1250 &smb_fname->st, &ft, true);
1251 if (!NT_STATUS_IS_OK(status)) {
1252 reply_unixerror(req, ERRDOS, ERRnoaccess);
1256 if (mode != FILE_ATTRIBUTE_NORMAL) {
1257 if (VALID_STAT_OF_DIR(smb_fname->st))
1262 if (file_set_dosmode(conn, fname, mode, &smb_fname->st, NULL,
1264 reply_unixerror(req, ERRDOS, ERRnoaccess);
1269 reply_outbuf(req, 0, 0);
1271 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1273 TALLOC_FREE(smb_fname);
1274 END_PROFILE(SMBsetatr);
1278 /****************************************************************************
1280 ****************************************************************************/
1282 void reply_dskattr(struct smb_request *req)
1284 connection_struct *conn = req->conn;
1285 uint64_t dfree,dsize,bsize;
1286 START_PROFILE(SMBdskattr);
1288 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1289 reply_unixerror(req, ERRHRD, ERRgeneral);
1290 END_PROFILE(SMBdskattr);
1294 reply_outbuf(req, 5, 0);
1296 if (Protocol <= PROTOCOL_LANMAN2) {
1297 double total_space, free_space;
1298 /* we need to scale this to a number that DOS6 can handle. We
1299 use floating point so we can handle large drives on systems
1300 that don't have 64 bit integers
1302 we end up displaying a maximum of 2G to DOS systems
1304 total_space = dsize * (double)bsize;
1305 free_space = dfree * (double)bsize;
1307 dsize = (uint64_t)((total_space+63*512) / (64*512));
1308 dfree = (uint64_t)((free_space+63*512) / (64*512));
1310 if (dsize > 0xFFFF) dsize = 0xFFFF;
1311 if (dfree > 0xFFFF) dfree = 0xFFFF;
1313 SSVAL(req->outbuf,smb_vwv0,dsize);
1314 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1315 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1316 SSVAL(req->outbuf,smb_vwv3,dfree);
1318 SSVAL(req->outbuf,smb_vwv0,dsize);
1319 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1320 SSVAL(req->outbuf,smb_vwv2,512);
1321 SSVAL(req->outbuf,smb_vwv3,dfree);
1324 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1326 END_PROFILE(SMBdskattr);
1331 * Utility function to split the filename from the directory.
1333 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1334 char **fname_dir_out,
1335 char **fname_mask_out)
1337 const char *p = NULL;
1338 char *fname_dir = NULL;
1339 char *fname_mask = NULL;
1341 p = strrchr_m(fname_in, '/');
1343 fname_dir = talloc_strdup(ctx, ".");
1344 fname_mask = talloc_strdup(ctx, fname_in);
1346 fname_dir = talloc_strndup(ctx, fname_in,
1347 PTR_DIFF(p, fname_in));
1348 fname_mask = talloc_strdup(ctx, p+1);
1351 if (!fname_dir || !fname_mask) {
1352 TALLOC_FREE(fname_dir);
1353 TALLOC_FREE(fname_mask);
1354 return NT_STATUS_NO_MEMORY;
1357 *fname_dir_out = fname_dir;
1358 *fname_mask_out = fname_mask;
1359 return NT_STATUS_OK;
1362 /****************************************************************************
1364 Can be called from SMBsearch, SMBffirst or SMBfunique.
1365 ****************************************************************************/
1367 void reply_search(struct smb_request *req)
1369 connection_struct *conn = req->conn;
1370 const char *mask = NULL;
1371 char *directory = NULL;
1375 struct timespec date;
1377 unsigned int numentries = 0;
1378 unsigned int maxentries = 0;
1379 bool finished = False;
1385 bool check_descend = False;
1386 bool expect_close = False;
1388 bool mask_contains_wcard = False;
1389 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1390 TALLOC_CTX *ctx = talloc_tos();
1391 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1393 START_PROFILE(SMBsearch);
1396 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1397 END_PROFILE(SMBsearch);
1401 if (lp_posix_pathnames()) {
1402 reply_unknown_new(req, req->cmd);
1403 END_PROFILE(SMBsearch);
1407 /* If we were called as SMBffirst then we must expect close. */
1408 if(req->cmd == SMBffirst) {
1409 expect_close = True;
1412 reply_outbuf(req, 1, 3);
1413 maxentries = SVAL(req->vwv+0, 0);
1414 dirtype = SVAL(req->vwv+1, 0);
1415 p = (const char *)req->buf + 1;
1416 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1417 &nt_status, &mask_contains_wcard);
1418 if (!NT_STATUS_IS_OK(nt_status)) {
1419 reply_nterror(req, nt_status);
1420 END_PROFILE(SMBsearch);
1424 nt_status = resolve_dfspath_wcard(ctx, conn,
1425 req->flags2 & FLAGS2_DFS_PATHNAMES,
1428 &mask_contains_wcard);
1429 if (!NT_STATUS_IS_OK(nt_status)) {
1430 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1431 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1432 ERRSRV, ERRbadpath);
1433 END_PROFILE(SMBsearch);
1436 reply_nterror(req, nt_status);
1437 END_PROFILE(SMBsearch);
1442 status_len = SVAL(p, 0);
1445 /* dirtype &= ~aDIR; */
1447 if (status_len == 0) {
1448 struct smb_filename *smb_fname = NULL;
1450 nt_status = unix_convert(ctx, conn, path, &smb_fname,
1451 UCF_ALLOW_WCARD_LCOMP);
1452 if (!NT_STATUS_IS_OK(nt_status)) {
1453 reply_nterror(req, nt_status);
1454 END_PROFILE(SMBsearch);
1458 nt_status = get_full_smb_filename(ctx, smb_fname, &directory);
1459 TALLOC_FREE(smb_fname);
1460 if (!NT_STATUS_IS_OK(nt_status)) {
1461 reply_nterror(req, nt_status);
1462 END_PROFILE(SMBsearch);
1466 nt_status = check_name(conn, directory);
1467 if (!NT_STATUS_IS_OK(nt_status)) {
1468 reply_nterror(req, nt_status);
1469 END_PROFILE(SMBsearch);
1473 p = strrchr_m(directory,'/');
1474 if ((p != NULL) && (*directory != '/')) {
1476 directory = talloc_strndup(ctx, directory,
1477 PTR_DIFF(p, directory));
1480 directory = talloc_strdup(ctx,".");
1484 reply_nterror(req, NT_STATUS_NO_MEMORY);
1485 END_PROFILE(SMBsearch);
1489 memset((char *)status,'\0',21);
1490 SCVAL(status,0,(dirtype & 0x1F));
1492 nt_status = dptr_create(conn,
1498 mask_contains_wcard,
1501 if (!NT_STATUS_IS_OK(nt_status)) {
1502 reply_nterror(req, nt_status);
1503 END_PROFILE(SMBsearch);
1506 dptr_num = dptr_dnum(conn->dirptr);
1510 memcpy(status,p,21);
1511 status_dirtype = CVAL(status,0) & 0x1F;
1512 if (status_dirtype != (dirtype & 0x1F)) {
1513 dirtype = status_dirtype;
1516 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1517 if (!conn->dirptr) {
1520 string_set(&conn->dirpath,dptr_path(dptr_num));
1521 mask = dptr_wcard(dptr_num);
1526 * For a 'continue' search we have no string. So
1527 * check from the initial saved string.
1529 mask_contains_wcard = ms_has_wild(mask);
1530 dirtype = dptr_attr(dptr_num);
1533 DEBUG(4,("dptr_num is %d\n",dptr_num));
1535 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1536 dptr_init_search_op(conn->dirptr);
1538 if ((dirtype&0x1F) == aVOLID) {
1539 char buf[DIR_STRUCT_SIZE];
1540 memcpy(buf,status,21);
1541 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1542 0,aVOLID,0,!allow_long_path_components)) {
1543 reply_nterror(req, NT_STATUS_NO_MEMORY);
1544 END_PROFILE(SMBsearch);
1547 dptr_fill(buf+12,dptr_num);
1548 if (dptr_zero(buf+12) && (status_len==0)) {
1553 if (message_push_blob(&req->outbuf,
1554 data_blob_const(buf, sizeof(buf)))
1556 reply_nterror(req, NT_STATUS_NO_MEMORY);
1557 END_PROFILE(SMBsearch);
1565 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1568 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1569 conn->dirpath,lp_dontdescend(SNUM(conn))));
1570 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1571 check_descend = True;
1574 for (i=numentries;(i<maxentries) && !finished;i++) {
1575 finished = !get_dir_entry(ctx,
1586 char buf[DIR_STRUCT_SIZE];
1587 memcpy(buf,status,21);
1588 if (!make_dir_struct(ctx,
1594 convert_timespec_to_time_t(date),
1595 !allow_long_path_components)) {
1596 reply_nterror(req, NT_STATUS_NO_MEMORY);
1597 END_PROFILE(SMBsearch);
1600 if (!dptr_fill(buf+12,dptr_num)) {
1603 if (message_push_blob(&req->outbuf,
1604 data_blob_const(buf, sizeof(buf)))
1606 reply_nterror(req, NT_STATUS_NO_MEMORY);
1607 END_PROFILE(SMBsearch);
1617 /* If we were called as SMBffirst with smb_search_id == NULL
1618 and no entries were found then return error and close dirptr
1621 if (numentries == 0) {
1622 dptr_close(&dptr_num);
1623 } else if(expect_close && status_len == 0) {
1624 /* Close the dptr - we know it's gone */
1625 dptr_close(&dptr_num);
1628 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1629 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1630 dptr_close(&dptr_num);
1633 if ((numentries == 0) && !mask_contains_wcard) {
1634 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1635 END_PROFILE(SMBsearch);
1639 SSVAL(req->outbuf,smb_vwv0,numentries);
1640 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1641 SCVAL(smb_buf(req->outbuf),0,5);
1642 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1644 /* The replies here are never long name. */
1645 SSVAL(req->outbuf, smb_flg2,
1646 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1647 if (!allow_long_path_components) {
1648 SSVAL(req->outbuf, smb_flg2,
1649 SVAL(req->outbuf, smb_flg2)
1650 & (~FLAGS2_LONG_PATH_COMPONENTS));
1653 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1654 SSVAL(req->outbuf, smb_flg2,
1655 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1658 directory = dptr_path(dptr_num);
1661 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1662 smb_fn_name(req->cmd),
1664 directory ? directory : "./",
1669 END_PROFILE(SMBsearch);
1673 /****************************************************************************
1674 Reply to a fclose (stop directory search).
1675 ****************************************************************************/
1677 void reply_fclose(struct smb_request *req)
1685 bool path_contains_wcard = False;
1686 TALLOC_CTX *ctx = talloc_tos();
1688 START_PROFILE(SMBfclose);
1690 if (lp_posix_pathnames()) {
1691 reply_unknown_new(req, req->cmd);
1692 END_PROFILE(SMBfclose);
1696 p = (const char *)req->buf + 1;
1697 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1698 &err, &path_contains_wcard);
1699 if (!NT_STATUS_IS_OK(err)) {
1700 reply_nterror(req, err);
1701 END_PROFILE(SMBfclose);
1705 status_len = SVAL(p,0);
1708 if (status_len == 0) {
1709 reply_doserror(req, ERRSRV, ERRsrverror);
1710 END_PROFILE(SMBfclose);
1714 memcpy(status,p,21);
1716 if(dptr_fetch(status+12,&dptr_num)) {
1717 /* Close the dptr - we know it's gone */
1718 dptr_close(&dptr_num);
1721 reply_outbuf(req, 1, 0);
1722 SSVAL(req->outbuf,smb_vwv0,0);
1724 DEBUG(3,("search close\n"));
1726 END_PROFILE(SMBfclose);
1730 /****************************************************************************
1732 ****************************************************************************/
1734 void reply_open(struct smb_request *req)
1736 connection_struct *conn = req->conn;
1737 struct smb_filename *smb_fname = NULL;
1749 uint32 create_disposition;
1750 uint32 create_options = 0;
1752 TALLOC_CTX *ctx = talloc_tos();
1754 START_PROFILE(SMBopen);
1757 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1761 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1762 deny_mode = SVAL(req->vwv+0, 0);
1763 dos_attr = SVAL(req->vwv+1, 0);
1765 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1766 STR_TERMINATE, &status);
1767 if (!NT_STATUS_IS_OK(status)) {
1768 reply_nterror(req, status);
1772 if (!map_open_params_to_ntcreate(
1773 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1774 &share_mode, &create_disposition, &create_options)) {
1775 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1776 END_PROFILE(SMBopen);
1780 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1781 if (!NT_STATUS_IS_OK(status)) {
1782 reply_nterror(req, status);
1786 status = SMB_VFS_CREATE_FILE(
1789 0, /* root_dir_fid */
1790 smb_fname, /* fname */
1791 access_mask, /* access_mask */
1792 share_mode, /* share_access */
1793 create_disposition, /* create_disposition*/
1794 create_options, /* create_options */
1795 dos_attr, /* file_attributes */
1796 oplock_request, /* oplock_request */
1797 0, /* allocation_size */
1803 if (!NT_STATUS_IS_OK(status)) {
1804 if (open_was_deferred(req->mid)) {
1805 /* We have re-scheduled this call. */
1808 reply_openerror(req, status);
1812 size = smb_fname->st.st_ex_size;
1813 fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st);
1814 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1817 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1818 close_file(req, fsp, ERROR_CLOSE);
1819 reply_doserror(req, ERRDOS,ERRnoaccess);
1823 reply_outbuf(req, 7, 0);
1824 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1825 SSVAL(req->outbuf,smb_vwv1,fattr);
1826 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1827 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1829 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1831 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1832 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1834 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1835 SCVAL(req->outbuf,smb_flg,
1836 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1839 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1840 SCVAL(req->outbuf,smb_flg,
1841 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1844 TALLOC_FREE(smb_fname);
1845 END_PROFILE(SMBopen);
1849 /****************************************************************************
1850 Reply to an open and X.
1851 ****************************************************************************/
1853 void reply_open_and_X(struct smb_request *req)
1855 connection_struct *conn = req->conn;
1856 struct smb_filename *smb_fname = NULL;
1861 /* Breakout the oplock request bits so we can set the
1862 reply bits separately. */
1863 int ex_oplock_request;
1864 int core_oplock_request;
1867 int smb_sattr = SVAL(req->vwv+4, 0);
1868 uint32 smb_time = make_unix_date3(req->vwv+6);
1876 uint64_t allocation_size;
1877 ssize_t retval = -1;
1880 uint32 create_disposition;
1881 uint32 create_options = 0;
1882 TALLOC_CTX *ctx = talloc_tos();
1884 START_PROFILE(SMBopenX);
1886 if (req->wct < 15) {
1887 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1891 open_flags = SVAL(req->vwv+2, 0);
1892 deny_mode = SVAL(req->vwv+3, 0);
1893 smb_attr = SVAL(req->vwv+5, 0);
1894 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1895 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1896 oplock_request = ex_oplock_request | core_oplock_request;
1897 smb_ofun = SVAL(req->vwv+8, 0);
1898 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1900 /* If it's an IPC, pass off the pipe handler. */
1902 if (lp_nt_pipe_support()) {
1903 reply_open_pipe_and_X(conn, req);
1905 reply_doserror(req, ERRSRV, ERRaccess);
1910 /* XXXX we need to handle passed times, sattr and flags */
1911 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1912 STR_TERMINATE, &status);
1913 if (!NT_STATUS_IS_OK(status)) {
1914 reply_nterror(req, status);
1918 if (!map_open_params_to_ntcreate(
1919 fname, deny_mode, smb_ofun, &access_mask,
1920 &share_mode, &create_disposition, &create_options)) {
1921 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1925 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1926 if (!NT_STATUS_IS_OK(status)) {
1927 reply_nterror(req, status);
1931 status = SMB_VFS_CREATE_FILE(
1934 0, /* root_dir_fid */
1935 smb_fname, /* fname */
1936 access_mask, /* access_mask */
1937 share_mode, /* share_access */
1938 create_disposition, /* create_disposition*/
1939 create_options, /* create_options */
1940 smb_attr, /* file_attributes */
1941 oplock_request, /* oplock_request */
1942 0, /* allocation_size */
1946 &smb_action); /* pinfo */
1948 if (!NT_STATUS_IS_OK(status)) {
1949 if (open_was_deferred(req->mid)) {
1950 /* We have re-scheduled this call. */
1953 reply_openerror(req, status);
1957 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1958 if the file is truncated or created. */
1959 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1960 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1961 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1962 close_file(req, fsp, ERROR_CLOSE);
1963 reply_nterror(req, NT_STATUS_DISK_FULL);
1966 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1968 close_file(req, fsp, ERROR_CLOSE);
1969 reply_nterror(req, NT_STATUS_DISK_FULL);
1972 smb_fname->st.st_ex_size =
1973 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1976 fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st);
1977 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1979 close_file(req, fsp, ERROR_CLOSE);
1980 reply_doserror(req, ERRDOS, ERRnoaccess);
1984 /* If the caller set the extended oplock request bit
1985 and we granted one (by whatever means) - set the
1986 correct bit for extended oplock reply.
1989 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1990 smb_action |= EXTENDED_OPLOCK_GRANTED;
1993 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1994 smb_action |= EXTENDED_OPLOCK_GRANTED;
1997 /* If the caller set the core oplock request bit
1998 and we granted one (by whatever means) - set the
1999 correct bit for core oplock reply.
2002 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2003 reply_outbuf(req, 19, 0);
2005 reply_outbuf(req, 15, 0);
2008 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2009 SCVAL(req->outbuf, smb_flg,
2010 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2013 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2014 SCVAL(req->outbuf, smb_flg,
2015 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2018 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2019 SSVAL(req->outbuf,smb_vwv3,fattr);
2020 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2021 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2023 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2025 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2026 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2027 SSVAL(req->outbuf,smb_vwv11,smb_action);
2029 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2030 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2035 TALLOC_FREE(smb_fname);
2036 END_PROFILE(SMBopenX);
2040 /****************************************************************************
2041 Reply to a SMBulogoffX.
2042 ****************************************************************************/
2044 void reply_ulogoffX(struct smb_request *req)
2046 struct smbd_server_connection *sconn = smbd_server_conn;
2049 START_PROFILE(SMBulogoffX);
2051 vuser = get_valid_user_struct(sconn, req->vuid);
2054 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2058 /* in user level security we are supposed to close any files
2059 open by this user */
2060 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2061 file_close_user(req->vuid);
2064 invalidate_vuid(sconn, req->vuid);
2066 reply_outbuf(req, 2, 0);
2068 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2070 END_PROFILE(SMBulogoffX);
2074 /****************************************************************************
2075 Reply to a mknew or a create.
2076 ****************************************************************************/
2078 void reply_mknew(struct smb_request *req)
2080 connection_struct *conn = req->conn;
2081 struct smb_filename *smb_fname = NULL;
2084 struct smb_file_time ft;
2086 int oplock_request = 0;
2088 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2089 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2090 uint32 create_disposition;
2091 uint32 create_options = 0;
2092 TALLOC_CTX *ctx = talloc_tos();
2094 START_PROFILE(SMBcreate);
2098 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2102 fattr = SVAL(req->vwv+0, 0);
2103 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2106 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2108 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2109 STR_TERMINATE, &status);
2110 if (!NT_STATUS_IS_OK(status)) {
2111 reply_nterror(req, status);
2115 if (fattr & aVOLID) {
2116 DEBUG(0,("Attempt to create file (%s) with volid set - "
2117 "please report this\n", fname));
2120 if(req->cmd == SMBmknew) {
2121 /* We should fail if file exists. */
2122 create_disposition = FILE_CREATE;
2124 /* Create if file doesn't exist, truncate if it does. */
2125 create_disposition = FILE_OVERWRITE_IF;
2128 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
2129 if (!NT_STATUS_IS_OK(status)) {
2130 reply_nterror(req, status);
2134 status = SMB_VFS_CREATE_FILE(
2137 0, /* root_dir_fid */
2138 smb_fname, /* fname */
2139 access_mask, /* access_mask */
2140 share_mode, /* share_access */
2141 create_disposition, /* create_disposition*/
2142 create_options, /* create_options */
2143 fattr, /* file_attributes */
2144 oplock_request, /* oplock_request */
2145 0, /* allocation_size */
2151 if (!NT_STATUS_IS_OK(status)) {
2152 if (open_was_deferred(req->mid)) {
2153 /* We have re-scheduled this call. */
2156 reply_openerror(req, status);
2160 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2161 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &smb_fname->st,
2163 if (!NT_STATUS_IS_OK(status)) {
2164 END_PROFILE(SMBcreate);
2168 reply_outbuf(req, 1, 0);
2169 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2171 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2172 SCVAL(req->outbuf,smb_flg,
2173 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2176 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2177 SCVAL(req->outbuf,smb_flg,
2178 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2181 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2182 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2183 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2186 TALLOC_FREE(smb_fname);
2187 END_PROFILE(SMBcreate);
2191 /****************************************************************************
2192 Reply to a create temporary file.
2193 ****************************************************************************/
2195 void reply_ctemp(struct smb_request *req)
2197 connection_struct *conn = req->conn;
2198 struct smb_filename *smb_fname = NULL;
2206 TALLOC_CTX *ctx = talloc_tos();
2208 START_PROFILE(SMBctemp);
2211 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2215 fattr = SVAL(req->vwv+0, 0);
2216 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2218 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2219 STR_TERMINATE, &status);
2220 if (!NT_STATUS_IS_OK(status)) {
2221 reply_nterror(req, status);
2225 fname = talloc_asprintf(ctx,
2229 fname = talloc_strdup(ctx, "TMXXXXXX");
2233 reply_nterror(req, NT_STATUS_NO_MEMORY);
2237 status = resolve_dfspath(ctx, conn,
2238 req->flags2 & FLAGS2_DFS_PATHNAMES,
2241 if (!NT_STATUS_IS_OK(status)) {
2242 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2243 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2244 ERRSRV, ERRbadpath);
2247 reply_nterror(req, status);
2251 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
2252 if (!NT_STATUS_IS_OK(status)) {
2253 reply_nterror(req, status);
2257 status = check_name(conn, smb_fname->base_name);
2258 if (!NT_STATUS_IS_OK(status)) {
2259 reply_nterror(req, status);
2263 tmpfd = mkstemp(smb_fname->base_name);
2265 reply_unixerror(req, ERRDOS, ERRnoaccess);
2269 SET_STAT_INVALID(smb_fname->st);
2270 SMB_VFS_STAT(conn, smb_fname->base_name, &smb_fname->st);
2272 /* We should fail if file does not exist. */
2273 status = SMB_VFS_CREATE_FILE(
2276 0, /* root_dir_fid */
2277 smb_fname, /* fname */
2278 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2279 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2280 FILE_OPEN, /* create_disposition*/
2281 0, /* create_options */
2282 fattr, /* file_attributes */
2283 oplock_request, /* oplock_request */
2284 0, /* allocation_size */
2290 /* close fd from mkstemp() */
2293 if (!NT_STATUS_IS_OK(status)) {
2294 if (open_was_deferred(req->mid)) {
2295 /* We have re-scheduled this call. */
2298 reply_openerror(req, status);
2302 reply_outbuf(req, 1, 0);
2303 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2305 /* the returned filename is relative to the directory */
2306 s = strrchr_m(fsp->fsp_name, '/');
2314 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2315 thing in the byte section. JRA */
2316 SSVALS(p, 0, -1); /* what is this? not in spec */
2318 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2320 reply_nterror(req, NT_STATUS_NO_MEMORY);
2324 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2325 SCVAL(req->outbuf, smb_flg,
2326 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2329 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2330 SCVAL(req->outbuf, smb_flg,
2331 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2334 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2335 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2336 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2338 TALLOC_FREE(smb_fname);
2339 END_PROFILE(SMBctemp);
2343 /*******************************************************************
2344 Check if a user is allowed to rename a file.
2345 ********************************************************************/
2347 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2348 uint16 dirtype, SMB_STRUCT_STAT *pst)
2352 if (!CAN_WRITE(conn)) {
2353 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2356 fmode = dos_mode(conn, fsp->fsp_name, pst);
2357 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2358 return NT_STATUS_NO_SUCH_FILE;
2361 if (S_ISDIR(pst->st_ex_mode)) {
2362 if (fsp->posix_open) {
2363 return NT_STATUS_OK;
2366 /* If no pathnames are open below this
2367 directory, allow the rename. */
2369 if (file_find_subpath(fsp)) {
2370 return NT_STATUS_ACCESS_DENIED;
2372 return NT_STATUS_OK;
2375 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2376 return NT_STATUS_OK;
2379 return NT_STATUS_ACCESS_DENIED;
2382 /*******************************************************************
2383 * unlink a file with all relevant access checks
2384 *******************************************************************/
2386 static NTSTATUS do_unlink(connection_struct *conn,
2387 struct smb_request *req,
2388 struct smb_filename *smb_fname,
2394 uint32 dirtype_orig = dirtype;
2397 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2399 if (!CAN_WRITE(conn)) {
2400 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2403 status = get_full_smb_filename(smb_fname, smb_fname, &fname);
2404 if (!NT_STATUS_IS_OK(status)) {
2408 if (SMB_VFS_LSTAT(conn, fname, &smb_fname->st) != 0) {
2409 return map_nt_error_from_unix(errno);
2412 fattr = dos_mode(conn, fname, &smb_fname->st);
2414 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2415 dirtype = aDIR|aARCH|aRONLY;
2418 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2420 return NT_STATUS_NO_SUCH_FILE;
2423 if (!dir_check_ftype(conn, fattr, dirtype)) {
2425 return NT_STATUS_FILE_IS_A_DIRECTORY;
2427 return NT_STATUS_NO_SUCH_FILE;
2430 if (dirtype_orig & 0x8000) {
2431 /* These will never be set for POSIX. */
2432 return NT_STATUS_NO_SUCH_FILE;
2436 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2437 return NT_STATUS_FILE_IS_A_DIRECTORY;
2440 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2441 return NT_STATUS_NO_SUCH_FILE;
2444 if (dirtype & 0xFF00) {
2445 /* These will never be set for POSIX. */
2446 return NT_STATUS_NO_SUCH_FILE;
2451 return NT_STATUS_NO_SUCH_FILE;
2454 /* Can't delete a directory. */
2456 return NT_STATUS_FILE_IS_A_DIRECTORY;
2461 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2462 return NT_STATUS_OBJECT_NAME_INVALID;
2463 #endif /* JRATEST */
2465 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2467 On a Windows share, a file with read-only dosmode can be opened with
2468 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2469 fails with NT_STATUS_CANNOT_DELETE error.
2471 This semantic causes a problem that a user can not
2472 rename a file with read-only dosmode on a Samba share
2473 from a Windows command prompt (i.e. cmd.exe, but can rename
2474 from Windows Explorer).
2477 if (!lp_delete_readonly(SNUM(conn))) {
2478 if (fattr & aRONLY) {
2479 return NT_STATUS_CANNOT_DELETE;
2483 /* On open checks the open itself will check the share mode, so
2484 don't do it here as we'll get it wrong. */
2486 status = SMB_VFS_CREATE_FILE
2489 0, /* root_dir_fid */
2490 smb_fname, /* fname */
2491 DELETE_ACCESS, /* access_mask */
2492 FILE_SHARE_NONE, /* share_access */
2493 FILE_OPEN, /* create_disposition*/
2494 FILE_NON_DIRECTORY_FILE, /* create_options */
2495 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2496 0, /* oplock_request */
2497 0, /* allocation_size */
2503 if (!NT_STATUS_IS_OK(status)) {
2504 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2505 nt_errstr(status)));
2509 /* The set is across all open files on this dev/inode pair. */
2510 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2511 close_file(req, fsp, NORMAL_CLOSE);
2512 return NT_STATUS_ACCESS_DENIED;
2515 return close_file(req, fsp, NORMAL_CLOSE);
2518 /****************************************************************************
2519 The guts of the unlink command, split out so it may be called by the NT SMB
2521 ****************************************************************************/
2523 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2524 uint32 dirtype, const char *name_in, bool has_wild)
2526 struct smb_filename *smb_fname = NULL;
2527 char *fname_dir = NULL;
2528 char *fname_mask = NULL;
2530 NTSTATUS status = NT_STATUS_OK;
2531 TALLOC_CTX *ctx = talloc_tos();
2533 status = unix_convert(ctx, conn, name_in, &smb_fname,
2534 has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
2535 if (!NT_STATUS_IS_OK(status)) {
2539 /* Split up the directory from the filename/mask. */
2540 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2541 &fname_dir, &fname_mask);
2542 if (!NT_STATUS_IS_OK(status)) {
2547 * We should only check the mangled cache
2548 * here if unix_convert failed. This means
2549 * that the path in 'mask' doesn't exist
2550 * on the file system and so we need to look
2551 * for a possible mangle. This patch from
2552 * Tine Smukavec <valentin.smukavec@hermes.si>.
2555 if (!VALID_STAT(smb_fname->st) &&
2556 mangle_is_mangled(fname_mask, conn->params)) {
2557 char *new_mask = NULL;
2558 mangle_lookup_name_from_8_3(ctx, fname_mask,
2559 &new_mask, conn->params);
2561 TALLOC_FREE(fname_mask);
2562 fname_mask = new_mask;
2569 * Only one file needs to be unlinked. Append the mask back
2570 * onto the directory.
2572 TALLOC_FREE(smb_fname->base_name);
2573 smb_fname->base_name = talloc_asprintf(smb_fname,
2577 if (!smb_fname->base_name) {
2578 status = NT_STATUS_NO_MEMORY;
2582 dirtype = FILE_ATTRIBUTE_NORMAL;
2585 status = check_name(conn, smb_fname->base_name);
2586 if (!NT_STATUS_IS_OK(status)) {
2590 status = do_unlink(conn, req, smb_fname, dirtype);
2591 if (!NT_STATUS_IS_OK(status)) {
2597 struct smb_Dir *dir_hnd = NULL;
2601 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2602 status = NT_STATUS_OBJECT_NAME_INVALID;
2606 if (strequal(fname_mask,"????????.???")) {
2607 TALLOC_FREE(fname_mask);
2608 fname_mask = talloc_strdup(ctx, "*");
2610 status = NT_STATUS_NO_MEMORY;
2615 status = check_name(conn, fname_dir);
2616 if (!NT_STATUS_IS_OK(status)) {
2620 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2622 if (dir_hnd == NULL) {
2623 status = map_nt_error_from_unix(errno);
2627 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2628 the pattern matches against the long name, otherwise the short name
2629 We don't implement this yet XXXX
2632 status = NT_STATUS_NO_SUCH_FILE;
2634 while ((dname = ReadDirName(dir_hnd, &offset,
2636 if (!is_visible_file(conn, fname_dir, dname,
2637 &smb_fname->st, true)) {
2641 /* Quick check for "." and ".." */
2642 if (ISDOT(dname) || ISDOTDOT(dname)) {
2646 if(!mask_match(dname, fname_mask,
2647 conn->case_sensitive)) {
2651 TALLOC_FREE(smb_fname->base_name);
2652 smb_fname->base_name =
2653 talloc_asprintf(smb_fname, "%s/%s",
2656 if (!smb_fname->base_name) {
2657 TALLOC_FREE(dir_hnd);
2658 status = NT_STATUS_NO_MEMORY;
2662 status = check_name(conn, smb_fname->base_name);
2663 if (!NT_STATUS_IS_OK(status)) {
2664 TALLOC_FREE(dir_hnd);
2668 status = do_unlink(conn, req, smb_fname, dirtype);
2669 if (!NT_STATUS_IS_OK(status)) {
2674 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2675 smb_fname->base_name));
2677 TALLOC_FREE(dir_hnd);
2680 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2681 status = map_nt_error_from_unix(errno);
2685 TALLOC_FREE(smb_fname);
2686 TALLOC_FREE(fname_dir);
2687 TALLOC_FREE(fname_mask);
2691 /****************************************************************************
2693 ****************************************************************************/
2695 void reply_unlink(struct smb_request *req)
2697 connection_struct *conn = req->conn;
2701 bool path_contains_wcard = False;
2702 TALLOC_CTX *ctx = talloc_tos();
2704 START_PROFILE(SMBunlink);
2707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2708 END_PROFILE(SMBunlink);
2712 dirtype = SVAL(req->vwv+0, 0);
2714 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2715 STR_TERMINATE, &status,
2716 &path_contains_wcard);
2717 if (!NT_STATUS_IS_OK(status)) {
2718 reply_nterror(req, status);
2719 END_PROFILE(SMBunlink);
2723 status = resolve_dfspath_wcard(ctx, conn,
2724 req->flags2 & FLAGS2_DFS_PATHNAMES,
2727 &path_contains_wcard);
2728 if (!NT_STATUS_IS_OK(status)) {
2729 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2730 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2731 ERRSRV, ERRbadpath);
2732 END_PROFILE(SMBunlink);
2735 reply_nterror(req, status);
2736 END_PROFILE(SMBunlink);
2740 DEBUG(3,("reply_unlink : %s\n",name));
2742 status = unlink_internals(conn, req, dirtype, name,
2743 path_contains_wcard);
2744 if (!NT_STATUS_IS_OK(status)) {
2745 if (open_was_deferred(req->mid)) {
2746 /* We have re-scheduled this call. */
2747 END_PROFILE(SMBunlink);
2750 reply_nterror(req, status);
2751 END_PROFILE(SMBunlink);
2755 reply_outbuf(req, 0, 0);
2756 END_PROFILE(SMBunlink);
2761 /****************************************************************************
2763 ****************************************************************************/
2765 static void fail_readraw(void)
2767 const char *errstr = talloc_asprintf(talloc_tos(),
2768 "FAIL ! reply_readbraw: socket write fail (%s)",
2773 exit_server_cleanly(errstr);
2776 /****************************************************************************
2777 Fake (read/write) sendfile. Returns -1 on read or write fail.
2778 ****************************************************************************/
2780 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2784 size_t tosend = nread;
2791 bufsize = MIN(nread, 65536);
2793 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2797 while (tosend > 0) {
2801 if (tosend > bufsize) {
2806 ret = read_file(fsp,buf,startpos,cur_read);
2812 /* If we had a short read, fill with zeros. */
2813 if (ret < cur_read) {
2814 memset(buf + ret, '\0', cur_read - ret);
2817 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2822 startpos += cur_read;
2826 return (ssize_t)nread;
2829 #if defined(WITH_SENDFILE)
2830 /****************************************************************************
2831 Deal with the case of sendfile reading less bytes from the file than
2832 requested. Fill with zeros (all we can do).
2833 ****************************************************************************/
2835 static void sendfile_short_send(files_struct *fsp,
2840 #define SHORT_SEND_BUFSIZE 1024
2841 if (nread < headersize) {
2842 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2843 "header for file %s (%s). Terminating\n",
2844 fsp->fsp_name, strerror(errno) ));
2845 exit_server_cleanly("sendfile_short_send failed");
2848 nread -= headersize;
2850 if (nread < smb_maxcnt) {
2851 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2853 exit_server_cleanly("sendfile_short_send: "
2857 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2858 "with zeros !\n", fsp->fsp_name));
2860 while (nread < smb_maxcnt) {
2862 * We asked for the real file size and told sendfile
2863 * to not go beyond the end of the file. But it can
2864 * happen that in between our fstat call and the
2865 * sendfile call the file was truncated. This is very
2866 * bad because we have already announced the larger
2867 * number of bytes to the client.
2869 * The best we can do now is to send 0-bytes, just as
2870 * a read from a hole in a sparse file would do.
2872 * This should happen rarely enough that I don't care
2873 * about efficiency here :-)
2877 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2878 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2879 exit_server_cleanly("sendfile_short_send: "
2880 "write_data failed");
2887 #endif /* defined WITH_SENDFILE */
2889 /****************************************************************************
2890 Return a readbraw error (4 bytes of zero).
2891 ****************************************************************************/
2893 static void reply_readbraw_error(void)
2897 if (write_data(smbd_server_fd(),header,4) != 4) {
2902 /****************************************************************************
2903 Use sendfile in readbraw.
2904 ****************************************************************************/
2906 static void send_file_readbraw(connection_struct *conn,
2907 struct smb_request *req,
2913 char *outbuf = NULL;
2916 #if defined(WITH_SENDFILE)
2918 * We can only use sendfile on a non-chained packet
2919 * but we can use on a non-oplocked file. tridge proved this
2920 * on a train in Germany :-). JRA.
2921 * reply_readbraw has already checked the length.
2924 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2925 (fsp->wcp == NULL) &&
2926 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2927 ssize_t sendfile_read = -1;
2929 DATA_BLOB header_blob;
2931 _smb_setlen(header,nread);
2932 header_blob = data_blob_const(header, 4);
2934 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2935 &header_blob, startpos, nread)) == -1) {
2936 /* Returning ENOSYS means no data at all was sent.
2937 * Do this as a normal read. */
2938 if (errno == ENOSYS) {
2939 goto normal_readbraw;
2943 * Special hack for broken Linux with no working sendfile. If we
2944 * return EINTR we sent the header but not the rest of the data.
2945 * Fake this up by doing read/write calls.
2947 if (errno == EINTR) {
2948 /* Ensure we don't do this again. */
2949 set_use_sendfile(SNUM(conn), False);
2950 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2952 if (fake_sendfile(fsp, startpos, nread) == -1) {
2953 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2954 fsp->fsp_name, strerror(errno) ));
2955 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2960 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2961 fsp->fsp_name, strerror(errno) ));
2962 exit_server_cleanly("send_file_readbraw sendfile failed");
2963 } else if (sendfile_read == 0) {
2965 * Some sendfile implementations return 0 to indicate
2966 * that there was a short read, but nothing was
2967 * actually written to the socket. In this case,
2968 * fallback to the normal read path so the header gets
2969 * the correct byte count.
2971 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2972 "bytes falling back to the normal read: "
2973 "%s\n", fsp->fsp_name));
2974 goto normal_readbraw;
2977 /* Deal with possible short send. */
2978 if (sendfile_read != 4+nread) {
2979 sendfile_short_send(fsp, sendfile_read, 4, nread);
2987 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2989 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2990 (unsigned)(nread+4)));
2991 reply_readbraw_error();
2996 ret = read_file(fsp,outbuf+4,startpos,nread);
2997 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3006 _smb_setlen(outbuf,ret);
3007 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3010 TALLOC_FREE(outbuf);
3013 /****************************************************************************
3014 Reply to a readbraw (core+ protocol).
3015 ****************************************************************************/
3017 void reply_readbraw(struct smb_request *req)
3019 connection_struct *conn = req->conn;
3020 ssize_t maxcount,mincount;
3024 struct lock_struct lock;
3028 START_PROFILE(SMBreadbraw);
3030 if (srv_is_signing_active(smbd_server_conn) ||
3031 is_encrypted_packet(req->inbuf)) {
3032 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3033 "raw reads/writes are disallowed.");
3037 reply_readbraw_error();
3038 END_PROFILE(SMBreadbraw);
3043 * Special check if an oplock break has been issued
3044 * and the readraw request croses on the wire, we must
3045 * return a zero length response here.
3048 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3051 * We have to do a check_fsp by hand here, as
3052 * we must always return 4 zero bytes on error,
3056 if (!fsp || !conn || conn != fsp->conn ||
3057 req->vuid != fsp->vuid ||
3058 fsp->is_directory || fsp->fh->fd == -1) {
3060 * fsp could be NULL here so use the value from the packet. JRA.
3062 DEBUG(3,("reply_readbraw: fnum %d not valid "
3064 (int)SVAL(req->vwv+0, 0)));
3065 reply_readbraw_error();
3066 END_PROFILE(SMBreadbraw);
3070 /* Do a "by hand" version of CHECK_READ. */
3071 if (!(fsp->can_read ||
3072 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3073 (fsp->access_mask & FILE_EXECUTE)))) {
3074 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3075 (int)SVAL(req->vwv+0, 0)));
3076 reply_readbraw_error();
3077 END_PROFILE(SMBreadbraw);
3081 flush_write_cache(fsp, READRAW_FLUSH);
3083 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3084 if(req->wct == 10) {
3086 * This is a large offset (64 bit) read.
3088 #ifdef LARGE_SMB_OFF_T
3090 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3092 #else /* !LARGE_SMB_OFF_T */
3095 * Ensure we haven't been sent a >32 bit offset.
3098 if(IVAL(req->vwv+8, 0) != 0) {
3099 DEBUG(0,("reply_readbraw: large offset "
3100 "(%x << 32) used and we don't support "
3101 "64 bit offsets.\n",
3102 (unsigned int)IVAL(req->vwv+8, 0) ));
3103 reply_readbraw_error();
3104 END_PROFILE(SMBreadbraw);
3108 #endif /* LARGE_SMB_OFF_T */
3111 DEBUG(0,("reply_readbraw: negative 64 bit "
3112 "readraw offset (%.0f) !\n",
3113 (double)startpos ));
3114 reply_readbraw_error();
3115 END_PROFILE(SMBreadbraw);
3120 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3121 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3123 /* ensure we don't overrun the packet size */
3124 maxcount = MIN(65535,maxcount);
3126 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3127 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3130 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3131 reply_readbraw_error();
3132 END_PROFILE(SMBreadbraw);
3136 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3137 size = st.st_ex_size;
3140 if (startpos >= size) {
3143 nread = MIN(maxcount,(size - startpos));
3146 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3147 if (nread < mincount)
3151 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3152 "min=%lu nread=%lu\n",
3153 fsp->fnum, (double)startpos,
3154 (unsigned long)maxcount,
3155 (unsigned long)mincount,
3156 (unsigned long)nread ) );
3158 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3160 DEBUG(5,("reply_readbraw finished\n"));
3162 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3164 END_PROFILE(SMBreadbraw);
3169 #define DBGC_CLASS DBGC_LOCKING
3171 /****************************************************************************
3172 Reply to a lockread (core+ protocol).
3173 ****************************************************************************/
3175 void reply_lockread(struct smb_request *req)
3177 connection_struct *conn = req->conn;
3184 struct byte_range_lock *br_lck = NULL;
3186 struct smbd_server_connection *sconn = smbd_server_conn;
3188 START_PROFILE(SMBlockread);
3191 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3192 END_PROFILE(SMBlockread);
3196 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3198 if (!check_fsp(conn, req, fsp)) {
3199 END_PROFILE(SMBlockread);
3203 if (!CHECK_READ(fsp,req)) {
3204 reply_doserror(req, ERRDOS, ERRbadaccess);
3205 END_PROFILE(SMBlockread);
3209 numtoread = SVAL(req->vwv+1, 0);
3210 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3212 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3214 reply_outbuf(req, 5, numtoread + 3);
3216 data = smb_buf(req->outbuf) + 3;
3219 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3220 * protocol request that predates the read/write lock concept.
3221 * Thus instead of asking for a read lock here we need to ask
3222 * for a write lock. JRA.
3223 * Note that the requested lock size is unaffected by max_recv.
3226 br_lck = do_lock(smbd_messaging_context(),
3229 (uint64_t)numtoread,
3233 False, /* Non-blocking lock. */
3237 TALLOC_FREE(br_lck);
3239 if (NT_STATUS_V(status)) {
3240 reply_nterror(req, status);
3241 END_PROFILE(SMBlockread);
3246 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3249 if (numtoread > sconn->smb1.negprot.max_recv) {
3250 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3251 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3252 (unsigned int)numtoread,
3253 (unsigned int)sconn->smb1.negprot.max_recv));
3254 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3256 nread = read_file(fsp,data,startpos,numtoread);
3259 reply_unixerror(req, ERRDOS, ERRnoaccess);
3260 END_PROFILE(SMBlockread);
3264 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3266 SSVAL(req->outbuf,smb_vwv0,nread);
3267 SSVAL(req->outbuf,smb_vwv5,nread+3);
3268 p = smb_buf(req->outbuf);
3269 SCVAL(p,0,0); /* pad byte. */
3272 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3273 fsp->fnum, (int)numtoread, (int)nread));
3275 END_PROFILE(SMBlockread);
3280 #define DBGC_CLASS DBGC_ALL
3282 /****************************************************************************
3284 ****************************************************************************/
3286 void reply_read(struct smb_request *req)
3288 connection_struct *conn = req->conn;
3295 struct lock_struct lock;
3296 struct smbd_server_connection *sconn = smbd_server_conn;
3298 START_PROFILE(SMBread);
3301 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3302 END_PROFILE(SMBread);
3306 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3308 if (!check_fsp(conn, req, fsp)) {
3309 END_PROFILE(SMBread);
3313 if (!CHECK_READ(fsp,req)) {
3314 reply_doserror(req, ERRDOS, ERRbadaccess);
3315 END_PROFILE(SMBread);
3319 numtoread = SVAL(req->vwv+1, 0);
3320 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3322 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3325 * The requested read size cannot be greater than max_recv. JRA.
3327 if (numtoread > sconn->smb1.negprot.max_recv) {
3328 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3329 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3330 (unsigned int)numtoread,
3331 (unsigned int)sconn->smb1.negprot.max_recv));
3332 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3335 reply_outbuf(req, 5, numtoread+3);
3337 data = smb_buf(req->outbuf) + 3;
3339 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3340 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3343 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3344 reply_doserror(req, ERRDOS,ERRlock);
3345 END_PROFILE(SMBread);
3350 nread = read_file(fsp,data,startpos,numtoread);
3353 reply_unixerror(req, ERRDOS,ERRnoaccess);
3357 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3359 SSVAL(req->outbuf,smb_vwv0,nread);
3360 SSVAL(req->outbuf,smb_vwv5,nread+3);
3361 SCVAL(smb_buf(req->outbuf),0,1);
3362 SSVAL(smb_buf(req->outbuf),1,nread);
3364 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3365 fsp->fnum, (int)numtoread, (int)nread ) );
3368 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3370 END_PROFILE(SMBread);
3374 /****************************************************************************
3376 ****************************************************************************/
3378 static int setup_readX_header(struct smb_request *req, char *outbuf,
3384 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3385 data = smb_buf(outbuf);
3387 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3389 SCVAL(outbuf,smb_vwv0,0xFF);
3390 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3391 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3392 SSVAL(outbuf,smb_vwv6,
3394 + 1 /* the wct field */
3395 + 12 * sizeof(uint16_t) /* vwv */
3396 + 2); /* the buflen field */
3397 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3398 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3399 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3400 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3404 /****************************************************************************
3405 Reply to a read and X - possibly using sendfile.
3406 ****************************************************************************/
3408 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3409 files_struct *fsp, SMB_OFF_T startpos,
3412 SMB_STRUCT_STAT sbuf;
3414 struct lock_struct lock;
3416 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3417 reply_unixerror(req, ERRDOS, ERRnoaccess);
3421 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3422 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3425 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3426 reply_doserror(req, ERRDOS, ERRlock);
3430 if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
3431 || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
3433 * We already know that we would do a short read, so don't
3434 * try the sendfile() path.
3436 goto nosendfile_read;
3439 #if defined(WITH_SENDFILE)
3441 * We can only use sendfile on a non-chained packet
3442 * but we can use on a non-oplocked file. tridge proved this
3443 * on a train in Germany :-). JRA.
3446 if (!req_is_in_chain(req) &&
3447 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3448 (fsp->wcp == NULL) &&
3449 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3450 uint8 headerbuf[smb_size + 12 * 2];
3454 * Set up the packet header before send. We
3455 * assume here the sendfile will work (get the
3456 * correct amount of data).
3459 header = data_blob_const(headerbuf, sizeof(headerbuf));
3461 construct_reply_common_req(req, (char *)headerbuf);
3462 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3464 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3465 /* Returning ENOSYS means no data at all was sent.
3466 Do this as a normal read. */
3467 if (errno == ENOSYS) {
3472 * Special hack for broken Linux with no working sendfile. If we
3473 * return EINTR we sent the header but not the rest of the data.
3474 * Fake this up by doing read/write calls.
3477 if (errno == EINTR) {
3478 /* Ensure we don't do this again. */
3479 set_use_sendfile(SNUM(conn), False);
3480 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3481 nread = fake_sendfile(fsp, startpos,
3484 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3485 fsp->fsp_name, strerror(errno) ));
3486 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3488 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3489 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3490 /* No outbuf here means successful sendfile. */
3494 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3495 fsp->fsp_name, strerror(errno) ));
3496 exit_server_cleanly("send_file_readX sendfile failed");
3497 } else if (nread == 0) {
3499 * Some sendfile implementations return 0 to indicate
3500 * that there was a short read, but nothing was
3501 * actually written to the socket. In this case,
3502 * fallback to the normal read path so the header gets
3503 * the correct byte count.
3505 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3506 "falling back to the normal read: %s\n",
3511 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3512 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3514 /* Deal with possible short send. */
3515 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3516 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3518 /* No outbuf here means successful sendfile. */
3519 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3520 SMB_PERFCOUNT_END(&req->pcd);
3528 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3529 uint8 headerbuf[smb_size + 2*12];
3531 construct_reply_common_req(req, (char *)headerbuf);
3532 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3534 /* Send out the header. */
3535 if (write_data(smbd_server_fd(), (char *)headerbuf,
3536 sizeof(headerbuf)) != sizeof(headerbuf)) {
3537 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3538 fsp->fsp_name, strerror(errno) ));
3539 exit_server_cleanly("send_file_readX sendfile failed");
3541 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3543 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3544 fsp->fsp_name, strerror(errno) ));
3545 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3552 reply_outbuf(req, 12, smb_maxcnt);
3554 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3556 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3559 reply_unixerror(req, ERRDOS, ERRnoaccess);
3563 setup_readX_header(req, (char *)req->outbuf, nread);
3565 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3566 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3572 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3573 TALLOC_FREE(req->outbuf);
3577 /****************************************************************************
3578 Reply to a read and X.
3579 ****************************************************************************/
3581 void reply_read_and_X(struct smb_request *req)
3583 connection_struct *conn = req->conn;
3587 bool big_readX = False;
3589 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3592 START_PROFILE(SMBreadX);
3594 if ((req->wct != 10) && (req->wct != 12)) {
3595 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3599 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3600 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3601 smb_maxcnt = SVAL(req->vwv+5, 0);
3603 /* If it's an IPC, pass off the pipe handler. */
3605 reply_pipe_read_and_X(req);
3606 END_PROFILE(SMBreadX);
3610 if (!check_fsp(conn, req, fsp)) {
3611 END_PROFILE(SMBreadX);
3615 if (!CHECK_READ(fsp,req)) {
3616 reply_doserror(req, ERRDOS,ERRbadaccess);
3617 END_PROFILE(SMBreadX);
3621 if (global_client_caps & CAP_LARGE_READX) {
3622 size_t upper_size = SVAL(req->vwv+7, 0);
3623 smb_maxcnt |= (upper_size<<16);
3624 if (upper_size > 1) {
3625 /* Can't do this on a chained packet. */
3626 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3627 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3628 END_PROFILE(SMBreadX);
3631 /* We currently don't do this on signed or sealed data. */
3632 if (srv_is_signing_active(smbd_server_conn) ||
3633 is_encrypted_packet(req->inbuf)) {
3634 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3635 END_PROFILE(SMBreadX);
3638 /* Is there room in the reply for this data ? */
3639 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3641 NT_STATUS_INVALID_PARAMETER);
3642 END_PROFILE(SMBreadX);
3649 if (req->wct == 12) {
3650 #ifdef LARGE_SMB_OFF_T
3652 * This is a large offset (64 bit) read.
3654 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3656 #else /* !LARGE_SMB_OFF_T */
3659 * Ensure we haven't been sent a >32 bit offset.
3662 if(IVAL(req->vwv+10, 0) != 0) {
3663 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3664 "used and we don't support 64 bit offsets.\n",
3665 (unsigned int)IVAL(req->vwv+10, 0) ));
3666 END_PROFILE(SMBreadX);
3667 reply_doserror(req, ERRDOS, ERRbadaccess);
3671 #endif /* LARGE_SMB_OFF_T */
3676 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3680 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3683 END_PROFILE(SMBreadX);
3687 /****************************************************************************
3688 Error replies to writebraw must have smb_wct == 1. Fix this up.
3689 ****************************************************************************/
3691 void error_to_writebrawerr(struct smb_request *req)
3693 uint8 *old_outbuf = req->outbuf;
3695 reply_outbuf(req, 1, 0);
3697 memcpy(req->outbuf, old_outbuf, smb_size);
3698 TALLOC_FREE(old_outbuf);
3701 /****************************************************************************
3702 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3703 ****************************************************************************/
3705 void reply_writebraw(struct smb_request *req)
3707 connection_struct *conn = req->conn;
3710 ssize_t total_written=0;
3711 size_t numtowrite=0;
3717 struct lock_struct lock;
3720 START_PROFILE(SMBwritebraw);
3723 * If we ever reply with an error, it must have the SMB command
3724 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3727 SCVAL(req->inbuf,smb_com,SMBwritec);
3729 if (srv_is_signing_active(smbd_server_conn)) {
3730 END_PROFILE(SMBwritebraw);
3731 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3732 "raw reads/writes are disallowed.");
3735 if (req->wct < 12) {
3736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3737 error_to_writebrawerr(req);
3738 END_PROFILE(SMBwritebraw);
3742 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3743 if (!check_fsp(conn, req, fsp)) {
3744 error_to_writebrawerr(req);
3745 END_PROFILE(SMBwritebraw);
3749 if (!CHECK_WRITE(fsp)) {
3750 reply_doserror(req, ERRDOS, ERRbadaccess);
3751 error_to_writebrawerr(req);
3752 END_PROFILE(SMBwritebraw);
3756 tcount = IVAL(req->vwv+1, 0);
3757 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3758 write_through = BITSETW(req->vwv+7,0);
3760 /* We have to deal with slightly different formats depending
3761 on whether we are using the core+ or lanman1.0 protocol */
3763 if(Protocol <= PROTOCOL_COREPLUS) {
3764 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3765 data = smb_buf(req->inbuf);
3767 numtowrite = SVAL(req->vwv+10, 0);
3768 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3771 /* Ensure we don't write bytes past the end of this packet. */
3772 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3773 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3774 error_to_writebrawerr(req);
3775 END_PROFILE(SMBwritebraw);
3779 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3780 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3783 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3784 reply_doserror(req, ERRDOS, ERRlock);
3785 error_to_writebrawerr(req);
3786 END_PROFILE(SMBwritebraw);
3791 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3794 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3795 "wrote=%d sync=%d\n",
3796 fsp->fnum, (double)startpos, (int)numtowrite,
3797 (int)nwritten, (int)write_through));
3799 if (nwritten < (ssize_t)numtowrite) {
3800 reply_unixerror(req, ERRHRD, ERRdiskfull);
3801 error_to_writebrawerr(req);
3805 total_written = nwritten;
3807 /* Allocate a buffer of 64k + length. */
3808 buf = TALLOC_ARRAY(NULL, char, 65540);
3810 reply_doserror(req, ERRDOS, ERRnomem);
3811 error_to_writebrawerr(req);
3815 /* Return a SMBwritebraw message to the redirector to tell
3816 * it to send more bytes */
3818 memcpy(buf, req->inbuf, smb_size);
3819 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3820 SCVAL(buf,smb_com,SMBwritebraw);
3821 SSVALS(buf,smb_vwv0,0xFFFF);
3823 if (!srv_send_smb(smbd_server_fd(),
3825 false, 0, /* no signing */
3826 IS_CONN_ENCRYPTED(conn),
3828 exit_server_cleanly("reply_writebraw: srv_send_smb "
3832 /* Now read the raw data into the buffer and write it */
3833 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3835 if (!NT_STATUS_IS_OK(status)) {
3836 exit_server_cleanly("secondary writebraw failed");
3839 /* Set up outbuf to return the correct size */
3840 reply_outbuf(req, 1, 0);
3842 if (numtowrite != 0) {
3844 if (numtowrite > 0xFFFF) {
3845 DEBUG(0,("reply_writebraw: Oversize secondary write "
3846 "raw requested (%u). Terminating\n",
3847 (unsigned int)numtowrite ));
3848 exit_server_cleanly("secondary writebraw failed");
3851 if (tcount > nwritten+numtowrite) {
3852 DEBUG(3,("reply_writebraw: Client overestimated the "
3854 (int)tcount,(int)nwritten,(int)numtowrite));
3857 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3859 if (!NT_STATUS_IS_OK(status)) {
3860 DEBUG(0,("reply_writebraw: Oversize secondary write "
3861 "raw read failed (%s). Terminating\n",
3862 nt_errstr(status)));
3863 exit_server_cleanly("secondary writebraw failed");
3866 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3867 if (nwritten == -1) {
3869 reply_unixerror(req, ERRHRD, ERRdiskfull);
3870 error_to_writebrawerr(req);
3874 if (nwritten < (ssize_t)numtowrite) {
3875 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3876 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3880 total_written += nwritten;
3885 SSVAL(req->outbuf,smb_vwv0,total_written);
3887 status = sync_file(conn, fsp, write_through);
3888 if (!NT_STATUS_IS_OK(status)) {
3889 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3890 fsp->fsp_name, nt_errstr(status) ));
3891 reply_nterror(req, status);
3892 error_to_writebrawerr(req);
3896 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3898 fsp->fnum, (double)startpos, (int)numtowrite,
3899 (int)total_written));
3901 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3903 /* We won't return a status if write through is not selected - this
3904 * follows what WfWg does */
3905 END_PROFILE(SMBwritebraw);
3907 if (!write_through && total_written==tcount) {
3909 #if RABBIT_PELLET_FIX
3911 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3912 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3915 if (!send_keepalive(smbd_server_fd())) {
3916 exit_server_cleanly("reply_writebraw: send of "
3917 "keepalive failed");
3920 TALLOC_FREE(req->outbuf);
3925 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3927 END_PROFILE(SMBwritebraw);
3932 #define DBGC_CLASS DBGC_LOCKING
3934 /****************************************************************************
3935 Reply to a writeunlock (core+).
3936 ****************************************************************************/
3938 void reply_writeunlock(struct smb_request *req)
3940 connection_struct *conn = req->conn;
3941 ssize_t nwritten = -1;
3945 NTSTATUS status = NT_STATUS_OK;
3947 struct lock_struct lock;
3949 START_PROFILE(SMBwriteunlock);
3952 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3953 END_PROFILE(SMBwriteunlock);
3957 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3959 if (!check_fsp(conn, req, fsp)) {
3960 END_PROFILE(SMBwriteunlock);
3964 if (!CHECK_WRITE(fsp)) {
3965 reply_doserror(req, ERRDOS,ERRbadaccess);
3966 END_PROFILE(SMBwriteunlock);
3970 numtowrite = SVAL(req->vwv+1, 0);
3971 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3972 data = (const char *)req->buf + 3;
3975 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3976 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3979 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3980 reply_doserror(req, ERRDOS, ERRlock);
3981 END_PROFILE(SMBwriteunlock);
3986 /* The special X/Open SMB protocol handling of
3987 zero length writes is *NOT* done for
3989 if(numtowrite == 0) {
3992 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3995 status = sync_file(conn, fsp, False /* write through */);
3996 if (!NT_STATUS_IS_OK(status)) {
3997 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3998 fsp->fsp_name, nt_errstr(status) ));
3999 reply_nterror(req, status);
4003 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
4004 reply_unixerror(req, ERRHRD, ERRdiskfull);
4009 status = do_unlock(smbd_messaging_context(),
4012 (uint64_t)numtowrite,
4016 if (NT_STATUS_V(status)) {
4017 reply_nterror(req, status);
4022 reply_outbuf(req, 1, 0);
4024 SSVAL(req->outbuf,smb_vwv0,nwritten);
4026 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4027 fsp->fnum, (int)numtowrite, (int)nwritten));
4031 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4034 END_PROFILE(SMBwriteunlock);
4039 #define DBGC_CLASS DBGC_ALL
4041 /****************************************************************************
4043 ****************************************************************************/
4045 void reply_write(struct smb_request *req)
4047 connection_struct *conn = req->conn;
4049 ssize_t nwritten = -1;
4053 struct lock_struct lock;
4056 START_PROFILE(SMBwrite);
4059 END_PROFILE(SMBwrite);
4060 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4064 /* If it's an IPC, pass off the pipe handler. */
4066 reply_pipe_write(req);
4067 END_PROFILE(SMBwrite);
4071 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4073 if (!check_fsp(conn, req, fsp)) {
4074 END_PROFILE(SMBwrite);
4078 if (!CHECK_WRITE(fsp)) {
4079 reply_doserror(req, ERRDOS, ERRbadaccess);
4080 END_PROFILE(SMBwrite);
4084 numtowrite = SVAL(req->vwv+1, 0);
4085 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4086 data = (const char *)req->buf + 3;
4088 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4089 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4092 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4093 reply_doserror(req, ERRDOS, ERRlock);
4094 END_PROFILE(SMBwrite);
4099 * X/Open SMB protocol says that if smb_vwv1 is
4100 * zero then the file size should be extended or
4101 * truncated to the size given in smb_vwv[2-3].
4104 if(numtowrite == 0) {
4106 * This is actually an allocate call, and set EOF. JRA.
4108 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4110 reply_nterror(req, NT_STATUS_DISK_FULL);
4113 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4115 reply_nterror(req, NT_STATUS_DISK_FULL);
4118 trigger_write_time_update_immediate(fsp);
4120 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4123 status = sync_file(conn, fsp, False);
4124 if (!NT_STATUS_IS_OK(status)) {
4125 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4126 fsp->fsp_name, nt_errstr(status) ));
4127 reply_nterror(req, status);
4131 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4132 reply_unixerror(req, ERRHRD, ERRdiskfull);
4136 reply_outbuf(req, 1, 0);
4138 SSVAL(req->outbuf,smb_vwv0,nwritten);
4140 if (nwritten < (ssize_t)numtowrite) {
4141 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4142 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4145 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4148 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4150 END_PROFILE(SMBwrite);
4154 /****************************************************************************
4155 Ensure a buffer is a valid writeX for recvfile purposes.
4156 ****************************************************************************/
4158 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4159 (2*14) + /* word count (including bcc) */ \
4162 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4165 connection_struct *conn = NULL;
4166 unsigned int doff = 0;
4167 size_t len = smb_len_large(inbuf);
4168 struct smbd_server_connection *sconn = smbd_server_conn;
4170 if (is_encrypted_packet(inbuf)) {
4171 /* Can't do this on encrypted
4176 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4180 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4181 CVAL(inbuf,smb_wct) != 14) {
4182 DEBUG(10,("is_valid_writeX_buffer: chained or "
4183 "invalid word length.\n"));
4187 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4189 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4193 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4196 if (IS_PRINT(conn)) {
4197 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4200 doff = SVAL(inbuf,smb_vwv11);
4202 numtowrite = SVAL(inbuf,smb_vwv10);
4204 if (len > doff && len - doff > 0xFFFF) {
4205 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4208 if (numtowrite == 0) {
4209 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4213 /* Ensure the sizes match up. */
4214 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4215 /* no pad byte...old smbclient :-( */
4216 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4218 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4222 if (len - doff != numtowrite) {
4223 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4224 "len = %u, doff = %u, numtowrite = %u\n",
4227 (unsigned int)numtowrite ));
4231 DEBUG(10,("is_valid_writeX_buffer: true "
4232 "len = %u, doff = %u, numtowrite = %u\n",
4235 (unsigned int)numtowrite ));
4240 /****************************************************************************
4241 Reply to a write and X.
4242 ****************************************************************************/
4244 void reply_write_and_X(struct smb_request *req)
4246 connection_struct *conn = req->conn;
4248 struct lock_struct lock;
4253 unsigned int smb_doff;
4254 unsigned int smblen;
4258 START_PROFILE(SMBwriteX);
4260 if ((req->wct != 12) && (req->wct != 14)) {
4261 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4262 END_PROFILE(SMBwriteX);
4266 numtowrite = SVAL(req->vwv+10, 0);
4267 smb_doff = SVAL(req->vwv+11, 0);
4268 smblen = smb_len(req->inbuf);
4270 if (req->unread_bytes > 0xFFFF ||
4271 (smblen > smb_doff &&
4272 smblen - smb_doff > 0xFFFF)) {
4273 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4276 if (req->unread_bytes) {
4277 /* Can't do a recvfile write on IPC$ */
4279 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4280 END_PROFILE(SMBwriteX);
4283 if (numtowrite != req->unread_bytes) {
4284 reply_doserror(req, ERRDOS, ERRbadmem);
4285 END_PROFILE(SMBwriteX);
4289 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4290 smb_doff + numtowrite > smblen) {
4291 reply_doserror(req, ERRDOS, ERRbadmem);
4292 END_PROFILE(SMBwriteX);
4297 /* If it's an IPC, pass off the pipe handler. */
4299 if (req->unread_bytes) {
4300 reply_doserror(req, ERRDOS, ERRbadmem);
4301 END_PROFILE(SMBwriteX);
4304 reply_pipe_write_and_X(req);
4305 END_PROFILE(SMBwriteX);
4309 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4310 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4311 write_through = BITSETW(req->vwv+7,0);
4313 if (!check_fsp(conn, req, fsp)) {
4314 END_PROFILE(SMBwriteX);
4318 if (!CHECK_WRITE(fsp)) {
4319 reply_doserror(req, ERRDOS, ERRbadaccess);
4320 END_PROFILE(SMBwriteX);
4324 data = smb_base(req->inbuf) + smb_doff;
4326 if(req->wct == 14) {
4327 #ifdef LARGE_SMB_OFF_T
4329 * This is a large offset (64 bit) write.
4331 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4333 #else /* !LARGE_SMB_OFF_T */
4336 * Ensure we haven't been sent a >32 bit offset.
4339 if(IVAL(req->vwv+12, 0) != 0) {
4340 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4341 "used and we don't support 64 bit offsets.\n",
4342 (unsigned int)IVAL(req->vwv+12, 0) ));
4343 reply_doserror(req, ERRDOS, ERRbadaccess);
4344 END_PROFILE(SMBwriteX);
4348 #endif /* LARGE_SMB_OFF_T */
4351 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4352 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4355 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4356 reply_doserror(req, ERRDOS, ERRlock);
4357 END_PROFILE(SMBwriteX);
4361 /* X/Open SMB protocol says that, unlike SMBwrite
4362 if the length is zero then NO truncation is
4363 done, just a write of zero. To truncate a file,
4366 if(numtowrite == 0) {
4370 if ((req->unread_bytes == 0) &&
4371 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4376 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4379 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4380 reply_unixerror(req, ERRHRD, ERRdiskfull);
4384 reply_outbuf(req, 6, 0);
4385 SSVAL(req->outbuf,smb_vwv2,nwritten);
4386 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4388 if (nwritten < (ssize_t)numtowrite) {
4389 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4390 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4393 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4394 fsp->fnum, (int)numtowrite, (int)nwritten));
4396 status = sync_file(conn, fsp, write_through);
4397 if (!NT_STATUS_IS_OK(status)) {
4398 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4399 fsp->fsp_name, nt_errstr(status) ));
4400 reply_nterror(req, status);
4404 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4406 END_PROFILE(SMBwriteX);
4411 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4413 END_PROFILE(SMBwriteX);
4417 /****************************************************************************
4419 ****************************************************************************/
4421 void reply_lseek(struct smb_request *req)
4423 connection_struct *conn = req->conn;
4429 START_PROFILE(SMBlseek);
4432 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4433 END_PROFILE(SMBlseek);
4437 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4439 if (!check_fsp(conn, req, fsp)) {
4443 flush_write_cache(fsp, SEEK_FLUSH);
4445 mode = SVAL(req->vwv+1, 0) & 3;
4446 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4447 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4456 res = fsp->fh->pos + startpos;
4467 if (umode == SEEK_END) {
4468 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4469 if(errno == EINVAL) {
4470 SMB_OFF_T current_pos = startpos;
4471 SMB_STRUCT_STAT sbuf;
4473 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4474 reply_unixerror(req, ERRDOS,
4476 END_PROFILE(SMBlseek);
4480 current_pos += sbuf.st_ex_size;
4482 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4487 reply_unixerror(req, ERRDOS, ERRnoaccess);
4488 END_PROFILE(SMBlseek);
4495 reply_outbuf(req, 2, 0);
4496 SIVAL(req->outbuf,smb_vwv0,res);
4498 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4499 fsp->fnum, (double)startpos, (double)res, mode));
4501 END_PROFILE(SMBlseek);
4505 /****************************************************************************
4507 ****************************************************************************/
4509 void reply_flush(struct smb_request *req)
4511 connection_struct *conn = req->conn;
4515 START_PROFILE(SMBflush);
4518 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4522 fnum = SVAL(req->vwv+0, 0);
4523 fsp = file_fsp(req, fnum);
4525 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4530 file_sync_all(conn);
4532 NTSTATUS status = sync_file(conn, fsp, True);
4533 if (!NT_STATUS_IS_OK(status)) {
4534 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4535 fsp->fsp_name, nt_errstr(status) ));
4536 reply_nterror(req, status);
4537 END_PROFILE(SMBflush);
4542 reply_outbuf(req, 0, 0);
4544 DEBUG(3,("flush\n"));
4545 END_PROFILE(SMBflush);
4549 /****************************************************************************
4551 conn POINTER CAN BE NULL HERE !
4552 ****************************************************************************/
4554 void reply_exit(struct smb_request *req)
4556 START_PROFILE(SMBexit);
4558 file_close_pid(req->smbpid, req->vuid);
4560 reply_outbuf(req, 0, 0);
4562 DEBUG(3,("exit\n"));
4564 END_PROFILE(SMBexit);
4568 /****************************************************************************
4569 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4570 ****************************************************************************/
4572 void reply_close(struct smb_request *req)
4574 connection_struct *conn = req->conn;
4575 NTSTATUS status = NT_STATUS_OK;
4576 files_struct *fsp = NULL;
4577 START_PROFILE(SMBclose);
4580 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4581 END_PROFILE(SMBclose);
4585 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4588 * We can only use check_fsp if we know it's not a directory.
4591 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4592 reply_doserror(req, ERRDOS, ERRbadfid);
4593 END_PROFILE(SMBclose);
4597 if(fsp->is_directory) {
4599 * Special case - close NT SMB directory handle.
4601 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4602 status = close_file(req, fsp, NORMAL_CLOSE);
4606 * Close ordinary file.
4609 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4610 fsp->fh->fd, fsp->fnum,
4611 conn->num_files_open));
4614 * Take care of any time sent in the close.
4617 t = srv_make_unix_date3(req->vwv+1);
4618 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4621 * close_file() returns the unix errno if an error
4622 * was detected on close - normally this is due to
4623 * a disk full error. If not then it was probably an I/O error.
4626 status = close_file(req, fsp, NORMAL_CLOSE);
4629 if (!NT_STATUS_IS_OK(status)) {
4630 reply_nterror(req, status);
4631 END_PROFILE(SMBclose);
4635 reply_outbuf(req, 0, 0);
4636 END_PROFILE(SMBclose);
4640 /****************************************************************************
4641 Reply to a writeclose (Core+ protocol).
4642 ****************************************************************************/
4644 void reply_writeclose(struct smb_request *req)
4646 connection_struct *conn = req->conn;
4648 ssize_t nwritten = -1;
4649 NTSTATUS close_status = NT_STATUS_OK;
4652 struct timespec mtime;
4654 struct lock_struct lock;
4656 START_PROFILE(SMBwriteclose);
4659 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4660 END_PROFILE(SMBwriteclose);
4664 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4666 if (!check_fsp(conn, req, fsp)) {
4667 END_PROFILE(SMBwriteclose);
4670 if (!CHECK_WRITE(fsp)) {
4671 reply_doserror(req, ERRDOS,ERRbadaccess);
4672 END_PROFILE(SMBwriteclose);
4676 numtowrite = SVAL(req->vwv+1, 0);
4677 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4678 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4679 data = (const char *)req->buf + 1;
4682 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4683 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4686 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4687 reply_doserror(req, ERRDOS,ERRlock);
4688 END_PROFILE(SMBwriteclose);
4693 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4695 set_close_write_time(fsp, mtime);
4698 * More insanity. W2K only closes the file if writelen > 0.
4703 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4705 close_status = close_file(req, fsp, NORMAL_CLOSE);
4708 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4709 fsp->fnum, (int)numtowrite, (int)nwritten,
4710 conn->num_files_open));
4712 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4713 reply_doserror(req, ERRHRD, ERRdiskfull);
4717 if(!NT_STATUS_IS_OK(close_status)) {
4718 reply_nterror(req, close_status);
4722 reply_outbuf(req, 1, 0);
4724 SSVAL(req->outbuf,smb_vwv0,nwritten);
4728 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4731 END_PROFILE(SMBwriteclose);
4736 #define DBGC_CLASS DBGC_LOCKING
4738 /****************************************************************************
4740 ****************************************************************************/
4742 void reply_lock(struct smb_request *req)
4744 connection_struct *conn = req->conn;
4745 uint64_t count,offset;
4748 struct byte_range_lock *br_lck = NULL;
4750 START_PROFILE(SMBlock);
4753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4754 END_PROFILE(SMBlock);
4758 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4760 if (!check_fsp(conn, req, fsp)) {
4761 END_PROFILE(SMBlock);
4765 count = (uint64_t)IVAL(req->vwv+1, 0);
4766 offset = (uint64_t)IVAL(req->vwv+3, 0);
4768 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4769 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4771 br_lck = do_lock(smbd_messaging_context(),
4778 False, /* Non-blocking lock. */
4783 TALLOC_FREE(br_lck);
4785 if (NT_STATUS_V(status)) {
4786 reply_nterror(req, status);
4787 END_PROFILE(SMBlock);
4791 reply_outbuf(req, 0, 0);
4793 END_PROFILE(SMBlock);
4797 /****************************************************************************
4799 ****************************************************************************/
4801 void reply_unlock(struct smb_request *req)
4803 connection_struct *conn = req->conn;
4804 uint64_t count,offset;
4808 START_PROFILE(SMBunlock);
4811 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4812 END_PROFILE(SMBunlock);
4816 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4818 if (!check_fsp(conn, req, fsp)) {
4819 END_PROFILE(SMBunlock);
4823 count = (uint64_t)IVAL(req->vwv+1, 0);
4824 offset = (uint64_t)IVAL(req->vwv+3, 0);
4826 status = do_unlock(smbd_messaging_context(),
4833 if (NT_STATUS_V(status)) {
4834 reply_nterror(req, status);
4835 END_PROFILE(SMBunlock);
4839 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4840 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4842 reply_outbuf(req, 0, 0);
4844 END_PROFILE(SMBunlock);
4849 #define DBGC_CLASS DBGC_ALL
4851 /****************************************************************************
4853 conn POINTER CAN BE NULL HERE !
4854 ****************************************************************************/
4856 void reply_tdis(struct smb_request *req)
4858 struct smbd_server_connection *sconn = smbd_server_conn;
4859 connection_struct *conn = req->conn;
4860 START_PROFILE(SMBtdis);
4863 DEBUG(4,("Invalid connection in tdis\n"));
4864 reply_doserror(req, ERRSRV, ERRinvnid);
4865 END_PROFILE(SMBtdis);
4871 close_cnum(sconn, conn,req->vuid);
4874 reply_outbuf(req, 0, 0);
4875 END_PROFILE(SMBtdis);
4879 /****************************************************************************
4881 conn POINTER CAN BE NULL HERE !
4882 ****************************************************************************/
4884 void reply_echo(struct smb_request *req)
4886 connection_struct *conn = req->conn;
4887 struct smb_perfcount_data local_pcd;
4888 struct smb_perfcount_data *cur_pcd;
4892 START_PROFILE(SMBecho);
4894 smb_init_perfcount_data(&local_pcd);
4897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4898 END_PROFILE(SMBecho);
4902 smb_reverb = SVAL(req->vwv+0, 0);
4904 reply_outbuf(req, 1, req->buflen);
4906 /* copy any incoming data back out */
4907 if (req->buflen > 0) {
4908 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4911 if (smb_reverb > 100) {
4912 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4916 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4918 /* this makes sure we catch the request pcd */
4919 if (seq_num == smb_reverb) {
4920 cur_pcd = &req->pcd;
4922 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4923 cur_pcd = &local_pcd;
4926 SSVAL(req->outbuf,smb_vwv0,seq_num);
4928 show_msg((char *)req->outbuf);
4929 if (!srv_send_smb(smbd_server_fd(),
4930 (char *)req->outbuf,
4931 true, req->seqnum+1,
4932 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4934 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4937 DEBUG(3,("echo %d times\n", smb_reverb));
4939 TALLOC_FREE(req->outbuf);
4941 END_PROFILE(SMBecho);
4945 /****************************************************************************
4946 Reply to a printopen.
4947 ****************************************************************************/
4949 void reply_printopen(struct smb_request *req)
4951 connection_struct *conn = req->conn;
4953 SMB_STRUCT_STAT sbuf;
4956 START_PROFILE(SMBsplopen);
4959 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4960 END_PROFILE(SMBsplopen);
4964 if (!CAN_PRINT(conn)) {
4965 reply_doserror(req, ERRDOS, ERRnoaccess);
4966 END_PROFILE(SMBsplopen);
4970 status = file_new(req, conn, &fsp);
4971 if(!NT_STATUS_IS_OK(status)) {
4972 reply_nterror(req, status);
4973 END_PROFILE(SMBsplopen);
4977 /* Open for exclusive use, write only. */
4978 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4980 if (!NT_STATUS_IS_OK(status)) {
4981 file_free(req, fsp);
4982 reply_nterror(req, status);
4983 END_PROFILE(SMBsplopen);
4987 reply_outbuf(req, 1, 0);
4988 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4990 DEBUG(3,("openprint fd=%d fnum=%d\n",
4991 fsp->fh->fd, fsp->fnum));
4993 END_PROFILE(SMBsplopen);
4997 /****************************************************************************
4998 Reply to a printclose.
4999 ****************************************************************************/
5001 void reply_printclose(struct smb_request *req)
5003 connection_struct *conn = req->conn;
5007 START_PROFILE(SMBsplclose);
5010 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5011 END_PROFILE(SMBsplclose);
5015 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5017 if (!check_fsp(conn, req, fsp)) {
5018 END_PROFILE(SMBsplclose);
5022 if (!CAN_PRINT(conn)) {
5023 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
5024 END_PROFILE(SMBsplclose);
5028 DEBUG(3,("printclose fd=%d fnum=%d\n",
5029 fsp->fh->fd,fsp->fnum));
5031 status = close_file(req, fsp, NORMAL_CLOSE);
5033 if(!NT_STATUS_IS_OK(status)) {
5034 reply_nterror(req, status);
5035 END_PROFILE(SMBsplclose);
5039 reply_outbuf(req, 0, 0);
5041 END_PROFILE(SMBsplclose);
5045 /****************************************************************************
5046 Reply to a printqueue.
5047 ****************************************************************************/
5049 void reply_printqueue(struct smb_request *req)
5051 connection_struct *conn = req->conn;
5055 START_PROFILE(SMBsplretq);
5058 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5059 END_PROFILE(SMBsplretq);
5063 max_count = SVAL(req->vwv+0, 0);
5064 start_index = SVAL(req->vwv+1, 0);
5066 /* we used to allow the client to get the cnum wrong, but that
5067 is really quite gross and only worked when there was only
5068 one printer - I think we should now only accept it if they
5069 get it right (tridge) */
5070 if (!CAN_PRINT(conn)) {
5071 reply_doserror(req, ERRDOS, ERRnoaccess);
5072 END_PROFILE(SMBsplretq);
5076 reply_outbuf(req, 2, 3);
5077 SSVAL(req->outbuf,smb_vwv0,0);
5078 SSVAL(req->outbuf,smb_vwv1,0);
5079 SCVAL(smb_buf(req->outbuf),0,1);
5080 SSVAL(smb_buf(req->outbuf),1,0);
5082 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5083 start_index, max_count));
5086 print_queue_struct *queue = NULL;
5087 print_status_struct status;
5088 int count = print_queue_status(SNUM(conn), &queue, &status);
5089 int num_to_get = ABS(max_count);
5090 int first = (max_count>0?start_index:start_index+max_count+1);
5096 num_to_get = MIN(num_to_get,count-first);
5099 for (i=first;i<first+num_to_get;i++) {
5103 srv_put_dos_date2(p,0,queue[i].time);
5104 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5105 SSVAL(p,5, queue[i].job);
5106 SIVAL(p,7,queue[i].size);
5108 srvstr_push(blob, req->flags2, p+12,
5109 queue[i].fs_user, 16, STR_ASCII);
5111 if (message_push_blob(
5114 blob, sizeof(blob))) == -1) {
5115 reply_nterror(req, NT_STATUS_NO_MEMORY);
5116 END_PROFILE(SMBsplretq);
5122 SSVAL(req->outbuf,smb_vwv0,count);
5123 SSVAL(req->outbuf,smb_vwv1,
5124 (max_count>0?first+count:first-1));
5125 SCVAL(smb_buf(req->outbuf),0,1);
5126 SSVAL(smb_buf(req->outbuf),1,28*count);
5131 DEBUG(3,("%d entries returned in queue\n",count));
5134 END_PROFILE(SMBsplretq);
5138 /****************************************************************************
5139 Reply to a printwrite.
5140 ****************************************************************************/
5142 void reply_printwrite(struct smb_request *req)
5144 connection_struct *conn = req->conn;
5149 START_PROFILE(SMBsplwr);
5152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5153 END_PROFILE(SMBsplwr);
5157 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5159 if (!check_fsp(conn, req, fsp)) {
5160 END_PROFILE(SMBsplwr);
5164 if (!CAN_PRINT(conn)) {
5165 reply_doserror(req, ERRDOS, ERRnoaccess);
5166 END_PROFILE(SMBsplwr);
5170 if (!CHECK_WRITE(fsp)) {
5171 reply_doserror(req, ERRDOS, ERRbadaccess);
5172 END_PROFILE(SMBsplwr);
5176 numtowrite = SVAL(req->buf, 1);
5178 if (req->buflen < numtowrite + 3) {
5179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5180 END_PROFILE(SMBsplwr);
5184 data = (const char *)req->buf + 3;
5186 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5187 reply_unixerror(req, ERRHRD, ERRdiskfull);
5188 END_PROFILE(SMBsplwr);
5192 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5194 END_PROFILE(SMBsplwr);
5198 /****************************************************************************
5200 ****************************************************************************/
5202 void reply_mkdir(struct smb_request *req)
5204 connection_struct *conn = req->conn;
5205 struct smb_filename *smb_dname = NULL;
5206 char *directory = NULL;
5208 TALLOC_CTX *ctx = talloc_tos();
5210 START_PROFILE(SMBmkdir);
5212 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5213 STR_TERMINATE, &status);
5214 if (!NT_STATUS_IS_OK(status)) {
5215 reply_nterror(req, status);
5219 status = resolve_dfspath(ctx, conn,
5220 req->flags2 & FLAGS2_DFS_PATHNAMES,
5223 if (!NT_STATUS_IS_OK(status)) {
5224 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5225 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5226 ERRSRV, ERRbadpath);
5229 reply_nterror(req, status);
5233 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
5234 if (!NT_STATUS_IS_OK(status)) {
5235 reply_nterror(req, status);
5239 status = check_name(conn, smb_dname->base_name);
5240 if (!NT_STATUS_IS_OK(status)) {
5241 reply_nterror(req, status);
5245 status = create_directory(conn, req, smb_dname);
5247 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5249 if (!NT_STATUS_IS_OK(status)) {
5251 if (!use_nt_status()
5252 && NT_STATUS_EQUAL(status,
5253 NT_STATUS_OBJECT_NAME_COLLISION)) {
5255 * Yes, in the DOS error code case we get a
5256 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5257 * samba4 torture test.
5259 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5262 reply_nterror(req, status);
5266 reply_outbuf(req, 0, 0);
5268 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5270 TALLOC_FREE(smb_dname);
5271 END_PROFILE(SMBmkdir);
5275 /****************************************************************************
5276 Static function used by reply_rmdir to delete an entire directory
5277 tree recursively. Return True on ok, False on fail.
5278 ****************************************************************************/
5280 static bool recursive_rmdir(TALLOC_CTX *ctx,
5281 connection_struct *conn,
5284 const char *dname = NULL;
5288 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5294 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5295 char *fullname = NULL;
5297 if (ISDOT(dname) || ISDOTDOT(dname)) {
5301 if (!is_visible_file(conn, directory, dname, &st, False)) {
5305 /* Construct the full name. */
5306 fullname = talloc_asprintf(ctx,
5316 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5321 if(st.st_ex_mode & S_IFDIR) {
5322 if(!recursive_rmdir(ctx, conn, fullname)) {
5326 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5330 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5334 TALLOC_FREE(fullname);
5336 TALLOC_FREE(dir_hnd);
5340 /****************************************************************************
5341 The internals of the rmdir code - called elsewhere.
5342 ****************************************************************************/
5344 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5345 connection_struct *conn,
5346 const char *directory)
5351 /* Might be a symlink. */
5352 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5353 return map_nt_error_from_unix(errno);
5356 if (S_ISLNK(st.st_ex_mode)) {
5357 /* Is what it points to a directory ? */
5358 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5359 return map_nt_error_from_unix(errno);
5361 if (!(S_ISDIR(st.st_ex_mode))) {
5362 return NT_STATUS_NOT_A_DIRECTORY;
5364 ret = SMB_VFS_UNLINK(conn,directory);
5366 ret = SMB_VFS_RMDIR(conn,directory);
5369 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5370 FILE_NOTIFY_CHANGE_DIR_NAME,
5372 return NT_STATUS_OK;
5375 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5377 * Check to see if the only thing in this directory are
5378 * vetoed files/directories. If so then delete them and
5379 * retry. If we fail to delete any of them (and we *don't*
5380 * do a recursive delete) then fail the rmdir.
5384 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5385 directory, NULL, 0);
5387 if(dir_hnd == NULL) {
5392 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5393 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5395 if (!is_visible_file(conn, directory, dname, &st, False))
5397 if(!IS_VETO_PATH(conn, dname)) {
5398 TALLOC_FREE(dir_hnd);
5404 /* We only have veto files/directories.
5405 * Are we allowed to delete them ? */
5407 if(!lp_recursive_veto_delete(SNUM(conn))) {
5408 TALLOC_FREE(dir_hnd);
5413 /* Do a recursive delete. */
5414 RewindDir(dir_hnd,&dirpos);
5415 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5416 char *fullname = NULL;
5418 if (ISDOT(dname) || ISDOTDOT(dname)) {
5421 if (!is_visible_file(conn, directory, dname, &st, False)) {
5425 fullname = talloc_asprintf(ctx,
5435 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5438 if(st.st_ex_mode & S_IFDIR) {
5439 if(!recursive_rmdir(ctx, conn, fullname)) {
5442 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5445 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5448 TALLOC_FREE(fullname);
5450 TALLOC_FREE(dir_hnd);
5451 /* Retry the rmdir */
5452 ret = SMB_VFS_RMDIR(conn,directory);
5458 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5459 "%s\n", directory,strerror(errno)));
5460 return map_nt_error_from_unix(errno);
5463 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5464 FILE_NOTIFY_CHANGE_DIR_NAME,
5467 return NT_STATUS_OK;
5470 /****************************************************************************
5472 ****************************************************************************/
5474 void reply_rmdir(struct smb_request *req)
5476 connection_struct *conn = req->conn;
5477 struct smb_filename *smb_dname = NULL;
5478 char *directory = NULL;
5480 TALLOC_CTX *ctx = talloc_tos();
5482 START_PROFILE(SMBrmdir);
5484 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5485 STR_TERMINATE, &status);
5486 if (!NT_STATUS_IS_OK(status)) {
5487 reply_nterror(req, status);
5491 status = resolve_dfspath(ctx, conn,
5492 req->flags2 & FLAGS2_DFS_PATHNAMES,
5495 if (!NT_STATUS_IS_OK(status)) {
5496 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5497 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5498 ERRSRV, ERRbadpath);
5501 reply_nterror(req, status);
5505 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
5506 if (!NT_STATUS_IS_OK(status)) {
5507 reply_nterror(req, status);
5511 status = get_full_smb_filename(ctx, smb_dname, &directory);
5512 if (!NT_STATUS_IS_OK(status)) {
5513 reply_nterror(req, status);
5517 status = check_name(conn, directory);
5518 if (!NT_STATUS_IS_OK(status)) {
5519 reply_nterror(req, status);
5523 dptr_closepath(directory, req->smbpid);
5524 status = rmdir_internals(ctx, conn, directory);
5525 if (!NT_STATUS_IS_OK(status)) {
5526 reply_nterror(req, status);
5530 reply_outbuf(req, 0, 0);
5532 DEBUG( 3, ( "rmdir %s\n", directory ) );
5534 TALLOC_FREE(smb_dname);
5535 END_PROFILE(SMBrmdir);
5539 /*******************************************************************
5540 Resolve wildcards in a filename rename.
5541 ********************************************************************/
5543 static bool resolve_wildcards(TALLOC_CTX *ctx,
5548 char *name2_copy = NULL;
5553 char *p,*p2, *pname1, *pname2;
5555 name2_copy = talloc_strdup(ctx, name2);
5560 pname1 = strrchr_m(name1,'/');
5561 pname2 = strrchr_m(name2_copy,'/');
5563 if (!pname1 || !pname2) {
5567 /* Truncate the copy of name2 at the last '/' */
5570 /* Now go past the '/' */
5574 root1 = talloc_strdup(ctx, pname1);
5575 root2 = talloc_strdup(ctx, pname2);
5577 if (!root1 || !root2) {
5581 p = strrchr_m(root1,'.');
5584 ext1 = talloc_strdup(ctx, p+1);
5586 ext1 = talloc_strdup(ctx, "");
5588 p = strrchr_m(root2,'.');
5591 ext2 = talloc_strdup(ctx, p+1);
5593 ext2 = talloc_strdup(ctx, "");
5596 if (!ext1 || !ext2) {
5604 /* Hmmm. Should this be mb-aware ? */
5607 } else if (*p2 == '*') {
5609 root2 = talloc_asprintf(ctx, "%s%s",
5628 /* Hmmm. Should this be mb-aware ? */
5631 } else if (*p2 == '*') {
5633 ext2 = talloc_asprintf(ctx, "%s%s",
5649 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5654 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5666 /****************************************************************************
5667 Ensure open files have their names updated. Updated to notify other smbd's
5669 ****************************************************************************/
5671 static void rename_open_files(connection_struct *conn,
5672 struct share_mode_lock *lck,
5673 const char *newname)
5676 bool did_rename = False;
5678 for(fsp = file_find_di_first(lck->id); fsp;
5679 fsp = file_find_di_next(fsp)) {
5680 /* fsp_name is a relative path under the fsp. To change this for other
5681 sharepaths we need to manipulate relative paths. */
5682 /* TODO - create the absolute path and manipulate the newname
5683 relative to the sharepath. */
5684 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5687 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5688 fsp->fnum, file_id_string_tos(&fsp->file_id),
5689 fsp->fsp_name, newname ));
5690 string_set(&fsp->fsp_name, newname);
5695 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5696 file_id_string_tos(&lck->id), newname ));
5699 /* Send messages to all smbd's (not ourself) that the name has changed. */
5700 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5704 /****************************************************************************
5705 We need to check if the source path is a parent directory of the destination
5706 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5707 refuse the rename with a sharing violation. Under UNIX the above call can
5708 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5709 probably need to check that the client is a Windows one before disallowing
5710 this as a UNIX client (one with UNIX extensions) can know the source is a
5711 symlink and make this decision intelligently. Found by an excellent bug
5712 report from <AndyLiebman@aol.com>.
5713 ****************************************************************************/
5715 static bool rename_path_prefix_equal(const char *src, const char *dest)
5717 const char *psrc = src;
5718 const char *pdst = dest;
5721 if (psrc[0] == '.' && psrc[1] == '/') {
5724 if (pdst[0] == '.' && pdst[1] == '/') {
5727 if ((slen = strlen(psrc)) > strlen(pdst)) {
5730 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5734 * Do the notify calls from a rename
5737 static void notify_rename(connection_struct *conn, bool is_dir,
5738 const char *oldpath, const char *newpath)
5740 char *olddir, *newdir;
5741 const char *oldname, *newname;
5744 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5745 : FILE_NOTIFY_CHANGE_FILE_NAME;
5747 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5748 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5749 TALLOC_FREE(olddir);
5753 if (strcmp(olddir, newdir) == 0) {
5754 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5755 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5758 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5759 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5761 TALLOC_FREE(olddir);
5762 TALLOC_FREE(newdir);
5764 /* this is a strange one. w2k3 gives an additional event for
5765 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5766 files, but not directories */
5768 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5769 FILE_NOTIFY_CHANGE_ATTRIBUTES
5770 |FILE_NOTIFY_CHANGE_CREATION,
5775 /****************************************************************************
5776 Rename an open file - given an fsp.
5777 ****************************************************************************/
5779 NTSTATUS rename_internals_fsp(connection_struct *conn,
5782 const char *newname_last_component,
5784 bool replace_if_exists)
5786 TALLOC_CTX *ctx = talloc_tos();
5787 SMB_STRUCT_STAT sbuf, sbuf1;
5788 NTSTATUS status = NT_STATUS_OK;
5789 struct share_mode_lock *lck = NULL;
5790 bool dst_exists, old_is_stream, new_is_stream;
5794 status = check_name(conn, newname);
5795 if (!NT_STATUS_IS_OK(status)) {
5799 /* Ensure newname contains a '/' */
5800 if(strrchr_m(newname,'/') == 0) {
5801 newname = talloc_asprintf(ctx,
5805 return NT_STATUS_NO_MEMORY;
5810 * Check for special case with case preserving and not
5811 * case sensitive. If the old last component differs from the original
5812 * last component only by case, then we should allow
5813 * the rename (user is trying to change the case of the
5817 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5818 strequal(newname, fsp->fsp_name)) {
5820 char *newname_modified_last_component = NULL;
5823 * Get the last component of the modified name.
5824 * Note that we guarantee that newname contains a '/'
5827 p = strrchr_m(newname,'/');
5828 newname_modified_last_component = talloc_strdup(ctx,
5830 if (!newname_modified_last_component) {
5831 return NT_STATUS_NO_MEMORY;
5834 if(strcsequal(newname_modified_last_component,
5835 newname_last_component) == False) {
5837 * Replace the modified last component with
5840 *p = '\0'; /* Truncate at the '/' */
5841 newname = talloc_asprintf(ctx,
5844 newname_last_component);
5849 * If the src and dest names are identical - including case,
5850 * don't do the rename, just return success.
5853 if (strcsequal(fsp->fsp_name, newname)) {
5854 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5856 return NT_STATUS_OK;
5859 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5860 new_is_stream = is_ntfs_stream_name(newname);
5862 /* Return the correct error code if both names aren't streams. */
5863 if (!old_is_stream && new_is_stream) {
5864 return NT_STATUS_OBJECT_NAME_INVALID;
5867 if (old_is_stream && !new_is_stream) {
5868 return NT_STATUS_INVALID_PARAMETER;
5872 * Have vfs_object_exist also fill sbuf1
5874 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5876 if(!replace_if_exists && dst_exists) {
5877 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5878 fsp->fsp_name,newname));
5879 return NT_STATUS_OBJECT_NAME_COLLISION;
5883 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5884 files_struct *dst_fsp = file_find_di_first(fileid);
5885 /* The file can be open when renaming a stream */
5886 if (dst_fsp && !new_is_stream) {
5887 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5888 return NT_STATUS_ACCESS_DENIED;
5892 /* Ensure we have a valid stat struct for the source. */
5893 if (fsp->fh->fd != -1) {
5894 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5895 return map_nt_error_from_unix(errno);
5899 if (fsp->posix_open) {
5900 ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
5902 ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
5905 return map_nt_error_from_unix(errno);
5909 status = can_rename(conn, fsp, attrs, &sbuf);
5911 if (!NT_STATUS_IS_OK(status)) {
5912 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5913 nt_errstr(status), fsp->fsp_name,newname));
5914 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5915 status = NT_STATUS_ACCESS_DENIED;
5919 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5920 return NT_STATUS_ACCESS_DENIED;
5923 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5927 * We have the file open ourselves, so not being able to get the
5928 * corresponding share mode lock is a fatal error.
5931 SMB_ASSERT(lck != NULL);
5933 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5934 uint32 create_options = fsp->fh->private_options;
5936 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5937 fsp->fsp_name,newname));
5939 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5941 rename_open_files(conn, lck, newname);
5944 * A rename acts as a new file create w.r.t. allowing an initial delete
5945 * on close, probably because in Windows there is a new handle to the
5946 * new file. If initial delete on close was requested but not
5947 * originally set, we need to set it here. This is probably not 100% correct,
5948 * but will work for the CIFSFS client which in non-posix mode
5949 * depends on these semantics. JRA.
5952 if (create_options & FILE_DELETE_ON_CLOSE) {
5953 status = can_set_delete_on_close(fsp, True, 0);
5955 if (NT_STATUS_IS_OK(status)) {
5956 /* Note that here we set the *inital* delete on close flag,
5957 * not the regular one. The magic gets handled in close. */
5958 fsp->initial_delete_on_close = True;
5962 return NT_STATUS_OK;
5967 if (errno == ENOTDIR || errno == EISDIR) {
5968 status = NT_STATUS_OBJECT_NAME_COLLISION;
5970 status = map_nt_error_from_unix(errno);
5973 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5974 nt_errstr(status), fsp->fsp_name,newname));
5979 /****************************************************************************
5980 The guts of the rename command, split out so it may be called by the NT SMB
5982 ****************************************************************************/
5984 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5985 connection_struct *conn,
5986 struct smb_request *req,
5987 const char *name_in,
5988 const char *newname_in,
5990 bool replace_if_exists,
5993 uint32_t access_mask)
5995 struct smb_filename *smb_fname_src = NULL;
5996 struct smb_filename *smb_fname_dst = NULL;
5997 char *fname_src_dir = NULL;
5998 char *fname_src_mask = NULL;
6000 NTSTATUS status = NT_STATUS_OK;
6001 struct smb_Dir *dir_hnd = NULL;
6004 int create_options = 0;
6005 bool posix_pathnames = lp_posix_pathnames();
6007 status = unix_convert(ctx, conn, name_in, &smb_fname_src,
6008 src_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6009 if (!NT_STATUS_IS_OK(status)) {
6013 status = unix_convert(ctx, conn, newname_in, &smb_fname_dst,
6015 (dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0)));
6016 if (!NT_STATUS_IS_OK(status)) {
6021 * Split the old name into directory and last component
6022 * strings. Note that unix_convert may have stripped off a
6023 * leading ./ from both name and newname if the rename is
6024 * at the root of the share. We need to make sure either both
6025 * name and newname contain a / character or neither of them do
6026 * as this is checked in resolve_wildcards().
6029 /* Split up the directory from the filename/mask. */
6030 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6031 &fname_src_dir, &fname_src_mask);
6032 if (!NT_STATUS_IS_OK(status)) {
6033 status = NT_STATUS_NO_MEMORY;
6038 * We should only check the mangled cache
6039 * here if unix_convert failed. This means
6040 * that the path in 'mask' doesn't exist
6041 * on the file system and so we need to look
6042 * for a possible mangle. This patch from
6043 * Tine Smukavec <valentin.smukavec@hermes.si>.
6046 if (!VALID_STAT(smb_fname_src->st) &&
6047 mangle_is_mangled(fname_src_mask, conn->params)) {
6048 char *new_mask = NULL;
6049 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6052 TALLOC_FREE(fname_src_mask);
6053 fname_src_mask = new_mask;
6057 if (!src_has_wild) {
6059 char *fname_src = NULL;
6060 char *fname_dst = NULL;
6063 * Only one file needs to be renamied. Append the mask back
6064 * onto the directory.
6066 TALLOC_FREE(smb_fname_src->base_name);
6067 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6071 if (!smb_fname_src->base_name) {
6072 status = NT_STATUS_NO_MEMORY;
6076 /* Ensure dst fname contains a '/' also */
6077 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6079 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6080 smb_fname_dst->base_name);
6082 status = NT_STATUS_NO_MEMORY;
6085 TALLOC_FREE(smb_fname_dst->base_name);
6086 smb_fname_dst->base_name = tmp;
6089 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6090 "case_preserve = %d, short case preserve = %d, "
6091 "directory = %s, newname = %s, "
6092 "last_component_dest = %s\n",
6093 conn->case_sensitive, conn->case_preserve,
6094 conn->short_case_preserve,
6095 smb_fname_str_dbg(smb_fname_src),
6096 smb_fname_str_dbg(smb_fname_dst),
6097 smb_fname_dst->original_lcomp));
6099 /* The dest name still may have wildcards. */
6100 if (dest_has_wild) {
6101 char *fname_dst_mod = NULL;
6102 if (!resolve_wildcards(smb_fname_dst,
6103 smb_fname_src->base_name,
6104 smb_fname_dst->base_name,
6106 DEBUG(6, ("rename_internals: resolve_wildcards "
6108 smb_fname_src->base_name,
6109 smb_fname_dst->base_name));
6110 status = NT_STATUS_NO_MEMORY;
6113 TALLOC_FREE(smb_fname_dst->base_name);
6114 smb_fname_dst->base_name = fname_dst_mod;
6117 status = get_full_smb_filename(ctx, smb_fname_src, &fname_src);
6118 if (!NT_STATUS_IS_OK(status)) {
6122 ZERO_STRUCT(smb_fname_src->st);
6123 if (posix_pathnames) {
6124 SMB_VFS_LSTAT(conn, fname_src, &smb_fname_src->st);
6126 SMB_VFS_STAT(conn, fname_src, &smb_fname_src->st);
6129 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6130 create_options |= FILE_DIRECTORY_FILE;
6133 TALLOC_FREE(fname_src);
6135 status = SMB_VFS_CREATE_FILE(
6138 0, /* root_dir_fid */
6139 smb_fname_src, /* fname */
6140 access_mask, /* access_mask */
6141 (FILE_SHARE_READ | /* share_access */
6143 FILE_OPEN, /* create_disposition*/
6144 create_options, /* create_options */
6145 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6146 0, /* oplock_request */
6147 0, /* allocation_size */
6153 if (!NT_STATUS_IS_OK(status)) {
6154 DEBUG(3, ("Could not open rename source %s: %s\n",
6155 smb_fname_str_dbg(smb_fname_src),
6156 nt_errstr(status)));
6160 status = get_full_smb_filename(ctx, smb_fname_dst, &fname_dst);
6161 if (!NT_STATUS_IS_OK(status)) {
6162 TALLOC_FREE(fname_src);
6166 status = rename_internals_fsp(conn, fsp, fname_dst,
6167 smb_fname_dst->original_lcomp,
6168 attrs, replace_if_exists);
6170 TALLOC_FREE(fname_dst);
6172 close_file(req, fsp, NORMAL_CLOSE);
6174 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6175 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6176 smb_fname_str_dbg(smb_fname_dst)));
6182 * Wildcards - process each file that matches.
6184 if (strequal(fname_src_mask, "????????.???")) {
6185 TALLOC_FREE(fname_src_mask);
6186 fname_src_mask = talloc_strdup(ctx, "*");
6187 if (!fname_src_mask) {
6188 status = NT_STATUS_NO_MEMORY;
6193 status = check_name(conn, fname_src_dir);
6194 if (!NT_STATUS_IS_OK(status)) {
6198 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6200 if (dir_hnd == NULL) {
6201 status = map_nt_error_from_unix(errno);
6205 status = NT_STATUS_NO_SUCH_FILE;
6207 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6208 * - gentest fix. JRA
6211 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
6212 files_struct *fsp = NULL;
6213 char *fname_src = NULL;
6214 char *fname_dst = NULL;
6215 char *destname = NULL;
6216 bool sysdir_entry = False;
6218 /* Quick check for "." and ".." */
6219 if (ISDOT(dname) || ISDOTDOT(dname)) {
6221 sysdir_entry = True;
6227 if (!is_visible_file(conn, fname_src_dir, dname,
6228 &smb_fname_src->st, false)) {
6232 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6237 status = NT_STATUS_OBJECT_NAME_INVALID;
6241 TALLOC_FREE(smb_fname_src->base_name);
6242 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6246 if (!smb_fname_src->base_name) {
6247 status = NT_STATUS_NO_MEMORY;
6251 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6252 smb_fname_dst->base_name,
6254 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6255 smb_fname_src->base_name, destname));
6259 status = NT_STATUS_NO_MEMORY;
6263 TALLOC_FREE(smb_fname_dst->base_name);
6264 smb_fname_dst->base_name = destname;
6266 status = get_full_smb_filename(ctx, smb_fname_src, &fname_src);
6267 if (!NT_STATUS_IS_OK(status)) {
6271 ZERO_STRUCT(smb_fname_src->st);
6272 if (posix_pathnames) {
6273 SMB_VFS_LSTAT(conn, fname_src, &smb_fname_src->st);
6275 SMB_VFS_STAT(conn, fname_src, &smb_fname_src->st);
6278 TALLOC_FREE(fname_src);
6282 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6283 create_options |= FILE_DIRECTORY_FILE;
6286 status = SMB_VFS_CREATE_FILE(
6289 0, /* root_dir_fid */
6290 smb_fname_src, /* fname */
6291 access_mask, /* access_mask */
6292 (FILE_SHARE_READ | /* share_access */
6294 FILE_OPEN, /* create_disposition*/
6295 create_options, /* create_options */
6296 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6297 0, /* oplock_request */
6298 0, /* allocation_size */
6304 if (!NT_STATUS_IS_OK(status)) {
6305 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6306 "returned %s rename %s -> %s\n",
6308 smb_fname_str_dbg(smb_fname_src),
6309 smb_fname_str_dbg(smb_fname_dst)));
6313 status = get_full_smb_filename(ctx, smb_fname_dst, &fname_dst);
6314 if (!NT_STATUS_IS_OK(status)) {
6318 status = rename_internals_fsp(conn, fsp, fname_dst, dname,
6319 attrs, replace_if_exists);
6321 TALLOC_FREE(fname_dst);
6323 close_file(req, fsp, NORMAL_CLOSE);
6325 if (!NT_STATUS_IS_OK(status)) {
6326 DEBUG(3, ("rename_internals_fsp returned %s for "
6327 "rename %s -> %s\n", nt_errstr(status),
6328 smb_fname_str_dbg(smb_fname_src),
6329 smb_fname_str_dbg(smb_fname_dst)));
6335 DEBUG(3,("rename_internals: doing rename on %s -> "
6336 "%s\n", smb_fname_str_dbg(smb_fname_src),
6337 smb_fname_str_dbg(smb_fname_src)));
6340 TALLOC_FREE(dir_hnd);
6342 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6343 status = map_nt_error_from_unix(errno);
6347 TALLOC_FREE(smb_fname_src);
6348 TALLOC_FREE(smb_fname_dst);
6349 TALLOC_FREE(fname_src_dir);
6350 TALLOC_FREE(fname_src_mask);
6354 /****************************************************************************
6356 ****************************************************************************/
6358 void reply_mv(struct smb_request *req)
6360 connection_struct *conn = req->conn;
6362 char *newname = NULL;
6366 bool src_has_wcard = False;
6367 bool dest_has_wcard = False;
6368 TALLOC_CTX *ctx = talloc_tos();
6370 START_PROFILE(SMBmv);
6373 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6378 attrs = SVAL(req->vwv+0, 0);
6380 p = (const char *)req->buf + 1;
6381 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6382 &status, &src_has_wcard);
6383 if (!NT_STATUS_IS_OK(status)) {
6384 reply_nterror(req, status);
6389 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6390 &status, &dest_has_wcard);
6391 if (!NT_STATUS_IS_OK(status)) {
6392 reply_nterror(req, status);
6397 status = resolve_dfspath_wcard(ctx, conn,
6398 req->flags2 & FLAGS2_DFS_PATHNAMES,
6402 if (!NT_STATUS_IS_OK(status)) {
6403 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6404 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6405 ERRSRV, ERRbadpath);
6409 reply_nterror(req, status);
6414 status = resolve_dfspath_wcard(ctx, conn,
6415 req->flags2 & FLAGS2_DFS_PATHNAMES,
6419 if (!NT_STATUS_IS_OK(status)) {
6420 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6421 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6422 ERRSRV, ERRbadpath);
6426 reply_nterror(req, status);
6431 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6433 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6434 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6435 if (!NT_STATUS_IS_OK(status)) {
6436 if (open_was_deferred(req->mid)) {
6437 /* We have re-scheduled this call. */
6441 reply_nterror(req, status);
6446 reply_outbuf(req, 0, 0);
6452 /*******************************************************************
6453 Copy a file as part of a reply_copy.
6454 ******************************************************************/
6457 * TODO: check error codes on all callers
6460 NTSTATUS copy_file(TALLOC_CTX *ctx,
6461 connection_struct *conn,
6462 struct smb_filename *smb_fname_src,
6463 struct smb_filename *smb_fname_dst,
6466 bool target_is_directory)
6468 struct smb_filename *smb_fname_dst_tmp = NULL;
6469 char *fname_src = NULL;
6470 char *fname_dst = NULL;
6472 files_struct *fsp1,*fsp2;
6474 uint32 new_create_disposition;
6478 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6479 if (!NT_STATUS_IS_OK(status)) {
6484 * If the target is a directory, extract the last component from the
6485 * src filename and append it to the dst filename
6487 if (target_is_directory) {
6490 /* dest/target can't be a stream if it's a directory. */
6491 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6493 p = strrchr_m(smb_fname_src->base_name,'/');
6497 p = smb_fname_src->base_name;
6499 smb_fname_dst_tmp->base_name =
6500 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6502 if (!smb_fname_dst_tmp->base_name) {
6503 status = NT_STATUS_NO_MEMORY;
6508 status = vfs_file_exist(conn, smb_fname_src);
6509 if (!NT_STATUS_IS_OK(status)) {
6513 if (!target_is_directory && count) {
6514 new_create_disposition = FILE_OPEN;
6516 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6517 0, ofun, NULL, NULL,
6518 &new_create_disposition,
6520 status = NT_STATUS_INVALID_PARAMETER;
6525 /* Open the src file for reading. */
6526 status = SMB_VFS_CREATE_FILE(
6529 0, /* root_dir_fid */
6530 smb_fname_src, /* fname */
6531 FILE_GENERIC_READ, /* access_mask */
6532 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6533 FILE_OPEN, /* create_disposition*/
6534 0, /* create_options */
6535 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6536 INTERNAL_OPEN_ONLY, /* oplock_request */
6537 0, /* allocation_size */
6543 if (!NT_STATUS_IS_OK(status)) {
6547 status = get_full_smb_filename(talloc_tos(), smb_fname_src, &fname_src);
6548 if (!NT_STATUS_IS_OK(status)) {
6552 dosattrs = dos_mode(conn, fname_src, &smb_fname_src->st);
6554 TALLOC_FREE(fname_src);
6556 status = get_full_smb_filename(talloc_tos(), smb_fname_dst_tmp, &fname_dst);
6557 if (!NT_STATUS_IS_OK(status)) {
6561 if (SMB_VFS_STAT(conn, fname_dst, &smb_fname_dst_tmp->st) == -1) {
6562 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6565 TALLOC_FREE(fname_dst);
6567 /* Open the dst file for writing. */
6568 status = SMB_VFS_CREATE_FILE(
6571 0, /* root_dir_fid */
6572 smb_fname_dst, /* fname */
6573 FILE_GENERIC_WRITE, /* access_mask */
6574 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6575 new_create_disposition, /* create_disposition*/
6576 0, /* create_options */
6577 dosattrs, /* file_attributes */
6578 INTERNAL_OPEN_ONLY, /* oplock_request */
6579 0, /* allocation_size */
6585 if (!NT_STATUS_IS_OK(status)) {
6586 close_file(NULL, fsp1, ERROR_CLOSE);
6590 if ((ofun&3) == 1) {
6591 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6592 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6594 * Stop the copy from occurring.
6597 smb_fname_src->st.st_ex_size = 0;
6601 /* Do the actual copy. */
6602 if (smb_fname_src->st.st_ex_size) {
6603 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6606 close_file(NULL, fsp1, NORMAL_CLOSE);
6608 /* Ensure the modtime is set correctly on the destination file. */
6609 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6612 * As we are opening fsp1 read-only we only expect
6613 * an error on close on fsp2 if we are out of space.
6614 * Thus we don't look at the error return from the
6617 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6619 if (!NT_STATUS_IS_OK(status)) {
6623 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6624 status = NT_STATUS_DISK_FULL;
6628 status = NT_STATUS_OK;
6631 TALLOC_FREE(smb_fname_dst_tmp);
6635 /****************************************************************************
6636 Reply to a file copy.
6637 ****************************************************************************/
6639 void reply_copy(struct smb_request *req)
6641 connection_struct *conn = req->conn;
6642 struct smb_filename *smb_fname_src = NULL;
6643 struct smb_filename *smb_fname_dst = NULL;
6644 char *fname_src = NULL;
6645 char *fname_dst = NULL;
6646 char *fname_src_mask = NULL;
6647 char *fname_src_dir = NULL;
6650 int error = ERRnoaccess;
6655 bool target_is_directory=False;
6656 bool source_has_wild = False;
6657 bool dest_has_wild = False;
6659 TALLOC_CTX *ctx = talloc_tos();
6661 START_PROFILE(SMBcopy);
6664 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6668 tid2 = SVAL(req->vwv+0, 0);
6669 ofun = SVAL(req->vwv+1, 0);
6670 flags = SVAL(req->vwv+2, 0);
6672 p = (const char *)req->buf;
6673 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6674 &status, &source_has_wild);
6675 if (!NT_STATUS_IS_OK(status)) {
6676 reply_nterror(req, status);
6679 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6680 &status, &dest_has_wild);
6681 if (!NT_STATUS_IS_OK(status)) {
6682 reply_nterror(req, status);
6686 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6688 if (tid2 != conn->cnum) {
6689 /* can't currently handle inter share copies XXXX */
6690 DEBUG(3,("Rejecting inter-share copy\n"));
6691 reply_doserror(req, ERRSRV, ERRinvdevice);
6695 status = resolve_dfspath_wcard(ctx, conn,
6696 req->flags2 & FLAGS2_DFS_PATHNAMES,
6700 if (!NT_STATUS_IS_OK(status)) {
6701 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6702 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6703 ERRSRV, ERRbadpath);
6706 reply_nterror(req, status);
6710 status = resolve_dfspath_wcard(ctx, conn,
6711 req->flags2 & FLAGS2_DFS_PATHNAMES,
6715 if (!NT_STATUS_IS_OK(status)) {
6716 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6717 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6718 ERRSRV, ERRbadpath);
6721 reply_nterror(req, status);
6725 status = unix_convert(ctx, conn, fname_src, &smb_fname_src,
6726 source_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6727 if (!NT_STATUS_IS_OK(status)) {
6728 reply_nterror(req, status);
6732 status = unix_convert(ctx, conn, fname_dst, &smb_fname_dst,
6733 dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6734 if (!NT_STATUS_IS_OK(status)) {
6735 reply_nterror(req, status);
6739 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6741 if ((flags&1) && target_is_directory) {
6742 reply_doserror(req, ERRDOS, ERRbadfile);
6746 if ((flags&2) && !target_is_directory) {
6747 reply_doserror(req, ERRDOS, ERRbadpath);
6751 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6752 /* wants a tree copy! XXXX */
6753 DEBUG(3,("Rejecting tree copy\n"));
6754 reply_doserror(req, ERRSRV, ERRerror);
6758 /* Split up the directory from the filename/mask. */
6759 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6760 &fname_src_dir, &fname_src_mask);
6761 if (!NT_STATUS_IS_OK(status)) {
6762 reply_nterror(req, NT_STATUS_NO_MEMORY);
6767 * We should only check the mangled cache
6768 * here if unix_convert failed. This means
6769 * that the path in 'mask' doesn't exist
6770 * on the file system and so we need to look
6771 * for a possible mangle. This patch from
6772 * Tine Smukavec <valentin.smukavec@hermes.si>.
6774 if (!VALID_STAT(smb_fname_src->st) &&
6775 mangle_is_mangled(fname_src_mask, conn->params)) {
6776 char *new_mask = NULL;
6777 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6778 &new_mask, conn->params);
6780 /* Use demangled name if one was successfully found. */
6782 TALLOC_FREE(fname_src_mask);
6783 fname_src_mask = new_mask;
6787 if (!source_has_wild) {
6790 * Only one file needs to be copied. Append the mask back onto
6793 TALLOC_FREE(smb_fname_src->base_name);
6794 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6798 if (!smb_fname_src->base_name) {
6799 reply_nterror(req, NT_STATUS_NO_MEMORY);
6803 if (dest_has_wild) {
6804 char *fname_dst_mod = NULL;
6805 if (!resolve_wildcards(smb_fname_dst,
6806 smb_fname_src->base_name,
6807 smb_fname_dst->base_name,
6809 reply_nterror(req, NT_STATUS_NO_MEMORY);
6812 TALLOC_FREE(smb_fname_dst->base_name);
6813 smb_fname_dst->base_name = fname_dst_mod;
6816 status = check_name(conn, smb_fname_src->base_name);
6817 if (!NT_STATUS_IS_OK(status)) {
6818 reply_nterror(req, status);
6822 status = check_name(conn, smb_fname_dst->base_name);
6823 if (!NT_STATUS_IS_OK(status)) {
6824 reply_nterror(req, status);
6828 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6829 ofun, count, target_is_directory);
6831 if(!NT_STATUS_IS_OK(status)) {
6832 reply_nterror(req, status);
6838 struct smb_Dir *dir_hnd = NULL;
6839 const char *dname = NULL;
6843 * There is a wildcard that requires us to actually read the
6844 * src dir and copy each file matching the mask to the dst.
6845 * Right now streams won't be copied, but this could
6846 * presumably be added with a nested loop for reach dir entry.
6848 SMB_ASSERT(!smb_fname_src->stream_name);
6849 SMB_ASSERT(!smb_fname_dst->stream_name);
6851 smb_fname_src->stream_name = NULL;
6852 smb_fname_dst->stream_name = NULL;
6854 if (strequal(fname_src_mask,"????????.???")) {
6855 TALLOC_FREE(fname_src_mask);
6856 fname_src_mask = talloc_strdup(ctx, "*");
6857 if (!fname_src_mask) {
6858 reply_nterror(req, NT_STATUS_NO_MEMORY);
6863 status = check_name(conn, fname_src_dir);
6864 if (!NT_STATUS_IS_OK(status)) {
6865 reply_nterror(req, status);
6869 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6870 if (dir_hnd == NULL) {
6871 status = map_nt_error_from_unix(errno);
6872 reply_nterror(req, status);
6878 /* Iterate over the src dir copying each entry to the dst. */
6879 while ((dname = ReadDirName(dir_hnd, &offset,
6880 &smb_fname_src->st))) {
6881 char *destname = NULL;
6883 if (ISDOT(dname) || ISDOTDOT(dname)) {
6887 if (!is_visible_file(conn, fname_src_dir, dname,
6888 &smb_fname_src->st, false)) {
6892 if(!mask_match(dname, fname_src_mask,
6893 conn->case_sensitive)) {
6897 error = ERRnoaccess;
6899 /* Get the src smb_fname struct setup. */
6900 TALLOC_FREE(smb_fname_src->base_name);
6901 smb_fname_src->base_name =
6902 talloc_asprintf(smb_fname_src, "%s/%s",
6903 fname_src_dir, dname);
6905 if (!smb_fname_src->base_name) {
6906 TALLOC_FREE(dir_hnd);
6907 reply_nterror(req, NT_STATUS_NO_MEMORY);
6911 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6912 smb_fname_dst->base_name,
6917 TALLOC_FREE(dir_hnd);
6918 reply_nterror(req, NT_STATUS_NO_MEMORY);
6922 TALLOC_FREE(smb_fname_dst->base_name);
6923 smb_fname_dst->base_name = destname;
6925 status = check_name(conn, smb_fname_src->base_name);
6926 if (!NT_STATUS_IS_OK(status)) {
6927 TALLOC_FREE(dir_hnd);
6928 reply_nterror(req, status);
6932 status = check_name(conn, smb_fname_dst->base_name);
6933 if (!NT_STATUS_IS_OK(status)) {
6934 TALLOC_FREE(dir_hnd);
6935 reply_nterror(req, status);
6939 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
6940 smb_fname_src->base_name,
6941 smb_fname_dst->base_name));
6943 status = copy_file(ctx, conn, smb_fname_src,
6944 smb_fname_dst, ofun, count,
6945 target_is_directory);
6946 if (NT_STATUS_IS_OK(status)) {
6950 TALLOC_FREE(dir_hnd);
6955 /* Error on close... */
6957 reply_unixerror(req, ERRHRD, ERRgeneral);
6961 reply_doserror(req, ERRDOS, error);
6965 reply_outbuf(req, 1, 0);
6966 SSVAL(req->outbuf,smb_vwv0,count);
6968 TALLOC_FREE(smb_fname_src);
6969 TALLOC_FREE(smb_fname_dst);
6970 TALLOC_FREE(fname_src);
6971 TALLOC_FREE(fname_dst);
6972 TALLOC_FREE(fname_src_mask);
6973 TALLOC_FREE(fname_src_dir);
6975 END_PROFILE(SMBcopy);
6980 #define DBGC_CLASS DBGC_LOCKING
6982 /****************************************************************************
6983 Get a lock pid, dealing with large count requests.
6984 ****************************************************************************/
6986 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6987 bool large_file_format)
6989 if(!large_file_format)
6990 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6992 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6995 /****************************************************************************
6996 Get a lock count, dealing with large count requests.
6997 ****************************************************************************/
6999 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7000 bool large_file_format)
7004 if(!large_file_format) {
7005 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7008 #if defined(HAVE_LONGLONG)
7009 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7010 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7011 #else /* HAVE_LONGLONG */
7014 * NT4.x seems to be broken in that it sends large file (64 bit)
7015 * lockingX calls even if the CAP_LARGE_FILES was *not*
7016 * negotiated. For boxes without large unsigned ints truncate the
7017 * lock count by dropping the top 32 bits.
7020 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7021 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7022 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7023 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7024 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7027 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7028 #endif /* HAVE_LONGLONG */
7034 #if !defined(HAVE_LONGLONG)
7035 /****************************************************************************
7036 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7037 ****************************************************************************/
7039 static uint32 map_lock_offset(uint32 high, uint32 low)
7043 uint32 highcopy = high;
7046 * Try and find out how many significant bits there are in high.
7049 for(i = 0; highcopy; i++)
7053 * We use 31 bits not 32 here as POSIX
7054 * lock offsets may not be negative.
7057 mask = (~0) << (31 - i);
7060 return 0; /* Fail. */
7066 #endif /* !defined(HAVE_LONGLONG) */
7068 /****************************************************************************
7069 Get a lock offset, dealing with large offset requests.
7070 ****************************************************************************/
7072 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7073 bool large_file_format, bool *err)
7075 uint64_t offset = 0;
7079 if(!large_file_format) {
7080 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7083 #if defined(HAVE_LONGLONG)
7084 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7085 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_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 mangle the
7092 * lock offset by mapping the top 32 bits onto the lower 32.
7095 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7096 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7097 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7100 if((new_low = map_lock_offset(high, low)) == 0) {
7102 return (uint64_t)-1;
7105 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7106 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7107 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7108 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7111 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7112 #endif /* HAVE_LONGLONG */
7118 /****************************************************************************
7119 Reply to a lockingX request.
7120 ****************************************************************************/
7122 void reply_lockingX(struct smb_request *req)
7124 connection_struct *conn = req->conn;
7126 unsigned char locktype;
7127 unsigned char oplocklevel;
7130 uint64_t count = 0, offset = 0;
7134 const uint8_t *data;
7135 bool large_file_format;
7137 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7139 START_PROFILE(SMBlockingX);
7142 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7143 END_PROFILE(SMBlockingX);
7147 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7148 locktype = CVAL(req->vwv+3, 0);
7149 oplocklevel = CVAL(req->vwv+3, 1);
7150 num_ulocks = SVAL(req->vwv+6, 0);
7151 num_locks = SVAL(req->vwv+7, 0);
7152 lock_timeout = IVAL(req->vwv+4, 0);
7153 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7155 if (!check_fsp(conn, req, fsp)) {
7156 END_PROFILE(SMBlockingX);
7162 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7163 /* we don't support these - and CANCEL_LOCK makes w2k
7164 and XP reboot so I don't really want to be
7165 compatible! (tridge) */
7166 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7167 END_PROFILE(SMBlockingX);
7171 /* Check if this is an oplock break on a file
7172 we have granted an oplock on.
7174 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7175 /* Client can insist on breaking to none. */
7176 bool break_to_none = (oplocklevel == 0);
7179 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7180 "for fnum = %d\n", (unsigned int)oplocklevel,
7184 * Make sure we have granted an exclusive or batch oplock on
7188 if (fsp->oplock_type == 0) {
7190 /* The Samba4 nbench simulator doesn't understand
7191 the difference between break to level2 and break
7192 to none from level2 - it sends oplock break
7193 replies in both cases. Don't keep logging an error
7194 message here - just ignore it. JRA. */
7196 DEBUG(5,("reply_lockingX: Error : oplock break from "
7197 "client for fnum = %d (oplock=%d) and no "
7198 "oplock granted on this file (%s).\n",
7199 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
7201 /* if this is a pure oplock break request then don't
7203 if (num_locks == 0 && num_ulocks == 0) {
7204 END_PROFILE(SMBlockingX);
7207 END_PROFILE(SMBlockingX);
7208 reply_doserror(req, ERRDOS, ERRlock);
7213 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7215 result = remove_oplock(fsp);
7217 result = downgrade_oplock(fsp);
7221 DEBUG(0, ("reply_lockingX: error in removing "
7222 "oplock on file %s\n", fsp->fsp_name));
7223 /* Hmmm. Is this panic justified? */
7224 smb_panic("internal tdb error");
7227 reply_to_oplock_break_requests(fsp);
7229 /* if this is a pure oplock break request then don't send a
7231 if (num_locks == 0 && num_ulocks == 0) {
7232 /* Sanity check - ensure a pure oplock break is not a
7234 if(CVAL(req->vwv+0, 0) != 0xff)
7235 DEBUG(0,("reply_lockingX: Error : pure oplock "
7236 "break is a chained %d request !\n",
7237 (unsigned int)CVAL(req->vwv+0, 0)));
7238 END_PROFILE(SMBlockingX);
7244 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7245 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7246 END_PROFILE(SMBlockingX);
7250 /* Data now points at the beginning of the list
7251 of smb_unlkrng structs */
7252 for(i = 0; i < (int)num_ulocks; i++) {
7253 lock_pid = get_lock_pid( data, i, large_file_format);
7254 count = get_lock_count( data, i, large_file_format);
7255 offset = get_lock_offset( data, i, large_file_format, &err);
7258 * There is no error code marked "stupid client bug".... :-).
7261 END_PROFILE(SMBlockingX);
7262 reply_doserror(req, ERRDOS, ERRnoaccess);
7266 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
7267 "pid %u, file %s\n", (double)offset, (double)count,
7268 (unsigned int)lock_pid, fsp->fsp_name ));
7270 status = do_unlock(smbd_messaging_context(),
7277 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
7278 nt_errstr(status)));
7280 if (NT_STATUS_V(status)) {
7281 END_PROFILE(SMBlockingX);
7282 reply_nterror(req, status);
7287 /* Setup the timeout in seconds. */
7289 if (!lp_blocking_locks(SNUM(conn))) {
7293 /* Now do any requested locks */
7294 data += ((large_file_format ? 20 : 10)*num_ulocks);
7296 /* Data now points at the beginning of the list
7297 of smb_lkrng structs */
7299 for(i = 0; i < (int)num_locks; i++) {
7300 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
7301 READ_LOCK:WRITE_LOCK);
7302 lock_pid = get_lock_pid( data, i, large_file_format);
7303 count = get_lock_count( data, i, large_file_format);
7304 offset = get_lock_offset( data, i, large_file_format, &err);
7307 * There is no error code marked "stupid client bug".... :-).
7310 END_PROFILE(SMBlockingX);
7311 reply_doserror(req, ERRDOS, ERRnoaccess);
7315 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
7316 "%u, file %s timeout = %d\n", (double)offset,
7317 (double)count, (unsigned int)lock_pid,
7318 fsp->fsp_name, (int)lock_timeout ));
7320 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7321 struct blocking_lock_record *blr = NULL;
7323 if (lp_blocking_locks(SNUM(conn))) {
7325 /* Schedule a message to ourselves to
7326 remove the blocking lock record and
7327 return the right error. */
7329 blr = blocking_lock_cancel(fsp,
7335 NT_STATUS_FILE_LOCK_CONFLICT);
7337 END_PROFILE(SMBlockingX);
7342 ERRcancelviolation));
7346 /* Remove a matching pending lock. */
7347 status = do_lock_cancel(fsp,
7354 bool blocking_lock = lock_timeout ? True : False;
7355 bool defer_lock = False;
7356 struct byte_range_lock *br_lck;
7357 uint32 block_smbpid;
7359 br_lck = do_lock(smbd_messaging_context(),
7371 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7372 /* Windows internal resolution for blocking locks seems
7373 to be about 200ms... Don't wait for less than that. JRA. */
7374 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7375 lock_timeout = lp_lock_spin_time();
7380 /* This heuristic seems to match W2K3 very well. If a
7381 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7382 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7383 far as I can tell. Replacement for do_lock_spin(). JRA. */
7385 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7386 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7388 lock_timeout = lp_lock_spin_time();
7391 if (br_lck && defer_lock) {
7393 * A blocking lock was requested. Package up
7394 * this smb into a queued request and push it
7395 * onto the blocking lock queue.
7397 if(push_blocking_lock_request(br_lck,
7408 TALLOC_FREE(br_lck);
7409 END_PROFILE(SMBlockingX);
7414 TALLOC_FREE(br_lck);
7417 if (NT_STATUS_V(status)) {
7418 END_PROFILE(SMBlockingX);
7419 reply_nterror(req, status);
7424 /* If any of the above locks failed, then we must unlock
7425 all of the previous locks (X/Open spec). */
7427 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7431 * Ensure we don't do a remove on the lock that just failed,
7432 * as under POSIX rules, if we have a lock already there, we
7433 * will delete it (and we shouldn't) .....
7435 for(i--; i >= 0; i--) {
7436 lock_pid = get_lock_pid( data, i, large_file_format);
7437 count = get_lock_count( data, i, large_file_format);
7438 offset = get_lock_offset( data, i, large_file_format,
7442 * There is no error code marked "stupid client
7446 END_PROFILE(SMBlockingX);
7447 reply_doserror(req, ERRDOS, ERRnoaccess);
7451 do_unlock(smbd_messaging_context(),
7458 END_PROFILE(SMBlockingX);
7459 reply_nterror(req, status);
7463 reply_outbuf(req, 2, 0);
7465 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7466 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7468 END_PROFILE(SMBlockingX);
7473 #define DBGC_CLASS DBGC_ALL
7475 /****************************************************************************
7476 Reply to a SMBreadbmpx (read block multiplex) request.
7477 Always reply with an error, if someone has a platform really needs this,
7478 please contact vl@samba.org
7479 ****************************************************************************/
7481 void reply_readbmpx(struct smb_request *req)
7483 START_PROFILE(SMBreadBmpx);
7484 reply_doserror(req, ERRSRV, ERRuseSTD);
7485 END_PROFILE(SMBreadBmpx);
7489 /****************************************************************************
7490 Reply to a SMBreadbs (read block multiplex secondary) request.
7491 Always reply with an error, if someone has a platform really needs this,
7492 please contact vl@samba.org
7493 ****************************************************************************/
7495 void reply_readbs(struct smb_request *req)
7497 START_PROFILE(SMBreadBs);
7498 reply_doserror(req, ERRSRV, ERRuseSTD);
7499 END_PROFILE(SMBreadBs);
7503 /****************************************************************************
7504 Reply to a SMBsetattrE.
7505 ****************************************************************************/
7507 void reply_setattrE(struct smb_request *req)
7509 connection_struct *conn = req->conn;
7510 struct smb_file_time ft;
7512 SMB_STRUCT_STAT sbuf;
7515 START_PROFILE(SMBsetattrE);
7519 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7520 END_PROFILE(SMBsetattrE);
7524 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7526 if(!fsp || (fsp->conn != conn)) {
7527 reply_doserror(req, ERRDOS, ERRbadfid);
7528 END_PROFILE(SMBsetattrE);
7534 * Convert the DOS times into unix times.
7537 ft.atime = convert_time_t_to_timespec(
7538 srv_make_unix_date2(req->vwv+3));
7539 ft.mtime = convert_time_t_to_timespec(
7540 srv_make_unix_date2(req->vwv+5));
7541 ft.create_time = convert_time_t_to_timespec(
7542 srv_make_unix_date2(req->vwv+1));
7544 reply_outbuf(req, 0, 0);
7547 * Patch from Ray Frush <frush@engr.colostate.edu>
7548 * Sometimes times are sent as zero - ignore them.
7551 /* Ensure we have a valid stat struct for the source. */
7552 if (fsp->fh->fd != -1) {
7553 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7554 status = map_nt_error_from_unix(errno);
7555 reply_nterror(req, status);
7556 END_PROFILE(SMBsetattrE);
7562 if (fsp->posix_open) {
7563 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
7565 ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
7568 status = map_nt_error_from_unix(errno);
7569 reply_nterror(req, status);
7570 END_PROFILE(SMBsetattrE);
7575 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7577 if (!NT_STATUS_IS_OK(status)) {
7578 reply_doserror(req, ERRDOS, ERRnoaccess);
7579 END_PROFILE(SMBsetattrE);
7583 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7586 (unsigned int)ft.atime.tv_sec,
7587 (unsigned int)ft.mtime.tv_sec,
7588 (unsigned int)ft.create_time.tv_sec
7591 END_PROFILE(SMBsetattrE);
7596 /* Back from the dead for OS/2..... JRA. */
7598 /****************************************************************************
7599 Reply to a SMBwritebmpx (write block multiplex primary) request.
7600 Always reply with an error, if someone has a platform really needs this,
7601 please contact vl@samba.org
7602 ****************************************************************************/
7604 void reply_writebmpx(struct smb_request *req)
7606 START_PROFILE(SMBwriteBmpx);
7607 reply_doserror(req, ERRSRV, ERRuseSTD);
7608 END_PROFILE(SMBwriteBmpx);
7612 /****************************************************************************
7613 Reply to a SMBwritebs (write block multiplex secondary) request.
7614 Always reply with an error, if someone has a platform really needs this,
7615 please contact vl@samba.org
7616 ****************************************************************************/
7618 void reply_writebs(struct smb_request *req)
7620 START_PROFILE(SMBwriteBs);
7621 reply_doserror(req, ERRSRV, ERRuseSTD);
7622 END_PROFILE(SMBwriteBs);
7626 /****************************************************************************
7627 Reply to a SMBgetattrE.
7628 ****************************************************************************/
7630 void reply_getattrE(struct smb_request *req)
7632 connection_struct *conn = req->conn;
7633 SMB_STRUCT_STAT sbuf;
7636 struct timespec create_ts;
7638 START_PROFILE(SMBgetattrE);
7641 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7642 END_PROFILE(SMBgetattrE);
7646 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7648 if(!fsp || (fsp->conn != conn)) {
7649 reply_doserror(req, ERRDOS, ERRbadfid);
7650 END_PROFILE(SMBgetattrE);
7654 /* Do an fstat on this file */
7655 if(fsp_stat(fsp, &sbuf)) {
7656 reply_unixerror(req, ERRDOS, ERRnoaccess);
7657 END_PROFILE(SMBgetattrE);
7661 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7664 * Convert the times into dos times. Set create
7665 * date to be last modify date as UNIX doesn't save
7669 reply_outbuf(req, 11, 0);
7671 create_ts = sbuf.st_ex_btime;
7672 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7673 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7674 convert_timespec_to_time_t(sbuf.st_ex_atime));
7675 /* Should we check pending modtime here ? JRA */
7676 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7677 convert_timespec_to_time_t(sbuf.st_ex_mtime));
7680 SIVAL(req->outbuf, smb_vwv6, 0);
7681 SIVAL(req->outbuf, smb_vwv8, 0);
7683 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7684 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_ex_size);
7685 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7687 SSVAL(req->outbuf,smb_vwv10, mode);
7689 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7691 END_PROFILE(SMBgetattrE);