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 = get_full_smb_filename(ctx, smb_fname, &fname);
1787 if (!NT_STATUS_IS_OK(status)) {
1788 reply_nterror(req, status);
1792 status = SMB_VFS_CREATE_FILE(
1795 0, /* root_dir_fid */
1797 0, /* create_file_flags */
1798 access_mask, /* access_mask */
1799 share_mode, /* share_access */
1800 create_disposition, /* create_disposition*/
1801 create_options, /* create_options */
1802 dos_attr, /* file_attributes */
1803 oplock_request, /* oplock_request */
1804 0, /* allocation_size */
1809 &smb_fname->st); /* psbuf */
1811 if (!NT_STATUS_IS_OK(status)) {
1812 if (open_was_deferred(req->mid)) {
1813 /* We have re-scheduled this call. */
1816 reply_openerror(req, status);
1820 size = smb_fname->st.st_ex_size;
1821 fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st);
1822 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1825 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1826 close_file(req, fsp, ERROR_CLOSE);
1827 reply_doserror(req, ERRDOS,ERRnoaccess);
1831 reply_outbuf(req, 7, 0);
1832 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1833 SSVAL(req->outbuf,smb_vwv1,fattr);
1834 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1835 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1837 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1839 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1840 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1842 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1843 SCVAL(req->outbuf,smb_flg,
1844 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1847 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1848 SCVAL(req->outbuf,smb_flg,
1849 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1852 TALLOC_FREE(smb_fname);
1853 END_PROFILE(SMBopen);
1857 /****************************************************************************
1858 Reply to an open and X.
1859 ****************************************************************************/
1861 void reply_open_and_X(struct smb_request *req)
1863 connection_struct *conn = req->conn;
1864 struct smb_filename *smb_fname = NULL;
1869 /* Breakout the oplock request bits so we can set the
1870 reply bits separately. */
1871 int ex_oplock_request;
1872 int core_oplock_request;
1875 int smb_sattr = SVAL(req->vwv+4, 0);
1876 uint32 smb_time = make_unix_date3(req->vwv+6);
1884 uint64_t allocation_size;
1885 ssize_t retval = -1;
1888 uint32 create_disposition;
1889 uint32 create_options = 0;
1890 TALLOC_CTX *ctx = talloc_tos();
1892 START_PROFILE(SMBopenX);
1894 if (req->wct < 15) {
1895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1899 open_flags = SVAL(req->vwv+2, 0);
1900 deny_mode = SVAL(req->vwv+3, 0);
1901 smb_attr = SVAL(req->vwv+5, 0);
1902 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1903 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1904 oplock_request = ex_oplock_request | core_oplock_request;
1905 smb_ofun = SVAL(req->vwv+8, 0);
1906 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1908 /* If it's an IPC, pass off the pipe handler. */
1910 if (lp_nt_pipe_support()) {
1911 reply_open_pipe_and_X(conn, req);
1913 reply_doserror(req, ERRSRV, ERRaccess);
1918 /* XXXX we need to handle passed times, sattr and flags */
1919 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1920 STR_TERMINATE, &status);
1921 if (!NT_STATUS_IS_OK(status)) {
1922 reply_nterror(req, status);
1926 if (!map_open_params_to_ntcreate(
1927 fname, deny_mode, smb_ofun, &access_mask,
1928 &share_mode, &create_disposition, &create_options)) {
1929 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1933 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1934 if (!NT_STATUS_IS_OK(status)) {
1935 reply_nterror(req, status);
1939 status = get_full_smb_filename(ctx, smb_fname, &fname);
1940 if (!NT_STATUS_IS_OK(status)) {
1941 reply_nterror(req, status);
1945 status = SMB_VFS_CREATE_FILE(
1948 0, /* root_dir_fid */
1950 0, /* create_file_flags */
1951 access_mask, /* access_mask */
1952 share_mode, /* share_access */
1953 create_disposition, /* create_disposition*/
1954 create_options, /* create_options */
1955 smb_attr, /* file_attributes */
1956 oplock_request, /* oplock_request */
1957 0, /* allocation_size */
1961 &smb_action, /* pinfo */
1962 &smb_fname->st); /* psbuf */
1964 if (!NT_STATUS_IS_OK(status)) {
1965 if (open_was_deferred(req->mid)) {
1966 /* We have re-scheduled this call. */
1969 reply_openerror(req, status);
1973 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1974 if the file is truncated or created. */
1975 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1976 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1977 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1978 close_file(req, fsp, ERROR_CLOSE);
1979 reply_nterror(req, NT_STATUS_DISK_FULL);
1982 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1984 close_file(req, fsp, ERROR_CLOSE);
1985 reply_nterror(req, NT_STATUS_DISK_FULL);
1988 smb_fname->st.st_ex_size =
1989 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1992 fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st);
1993 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1995 close_file(req, fsp, ERROR_CLOSE);
1996 reply_doserror(req, ERRDOS, ERRnoaccess);
2000 /* If the caller set the extended oplock request bit
2001 and we granted one (by whatever means) - set the
2002 correct bit for extended oplock reply.
2005 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2006 smb_action |= EXTENDED_OPLOCK_GRANTED;
2009 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2010 smb_action |= EXTENDED_OPLOCK_GRANTED;
2013 /* If the caller set the core oplock request bit
2014 and we granted one (by whatever means) - set the
2015 correct bit for core oplock reply.
2018 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2019 reply_outbuf(req, 19, 0);
2021 reply_outbuf(req, 15, 0);
2024 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2025 SCVAL(req->outbuf, smb_flg,
2026 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2029 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2030 SCVAL(req->outbuf, smb_flg,
2031 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2034 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2035 SSVAL(req->outbuf,smb_vwv3,fattr);
2036 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2037 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2039 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2041 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2042 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2043 SSVAL(req->outbuf,smb_vwv11,smb_action);
2045 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2046 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2051 TALLOC_FREE(smb_fname);
2052 END_PROFILE(SMBopenX);
2056 /****************************************************************************
2057 Reply to a SMBulogoffX.
2058 ****************************************************************************/
2060 void reply_ulogoffX(struct smb_request *req)
2062 struct smbd_server_connection *sconn = smbd_server_conn;
2065 START_PROFILE(SMBulogoffX);
2067 vuser = get_valid_user_struct(sconn, req->vuid);
2070 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2074 /* in user level security we are supposed to close any files
2075 open by this user */
2076 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2077 file_close_user(req->vuid);
2080 invalidate_vuid(sconn, req->vuid);
2082 reply_outbuf(req, 2, 0);
2084 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2086 END_PROFILE(SMBulogoffX);
2090 /****************************************************************************
2091 Reply to a mknew or a create.
2092 ****************************************************************************/
2094 void reply_mknew(struct smb_request *req)
2096 connection_struct *conn = req->conn;
2097 struct smb_filename *smb_fname = NULL;
2100 struct smb_file_time ft;
2102 int oplock_request = 0;
2104 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2105 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2106 uint32 create_disposition;
2107 uint32 create_options = 0;
2108 TALLOC_CTX *ctx = talloc_tos();
2110 START_PROFILE(SMBcreate);
2114 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2118 fattr = SVAL(req->vwv+0, 0);
2119 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2122 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2124 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2125 STR_TERMINATE, &status);
2126 if (!NT_STATUS_IS_OK(status)) {
2127 reply_nterror(req, status);
2131 if (fattr & aVOLID) {
2132 DEBUG(0,("Attempt to create file (%s) with volid set - "
2133 "please report this\n", fname));
2136 if(req->cmd == SMBmknew) {
2137 /* We should fail if file exists. */
2138 create_disposition = FILE_CREATE;
2140 /* Create if file doesn't exist, truncate if it does. */
2141 create_disposition = FILE_OVERWRITE_IF;
2144 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
2145 if (!NT_STATUS_IS_OK(status)) {
2146 reply_nterror(req, status);
2150 status = get_full_smb_filename(ctx, smb_fname, &fname);
2151 if (!NT_STATUS_IS_OK(status)) {
2152 reply_nterror(req, status);
2156 status = SMB_VFS_CREATE_FILE(
2159 0, /* root_dir_fid */
2161 0, /* create_file_flags */
2162 access_mask, /* access_mask */
2163 share_mode, /* share_access */
2164 create_disposition, /* create_disposition*/
2165 create_options, /* create_options */
2166 fattr, /* file_attributes */
2167 oplock_request, /* oplock_request */
2168 0, /* allocation_size */
2173 &smb_fname->st); /* psbuf */
2175 if (!NT_STATUS_IS_OK(status)) {
2176 if (open_was_deferred(req->mid)) {
2177 /* We have re-scheduled this call. */
2180 reply_openerror(req, status);
2184 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2185 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &smb_fname->st,
2187 if (!NT_STATUS_IS_OK(status)) {
2188 END_PROFILE(SMBcreate);
2192 reply_outbuf(req, 1, 0);
2193 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2195 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2196 SCVAL(req->outbuf,smb_flg,
2197 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2200 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2201 SCVAL(req->outbuf,smb_flg,
2202 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2205 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2206 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2207 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2210 TALLOC_FREE(smb_fname);
2211 END_PROFILE(SMBcreate);
2215 /****************************************************************************
2216 Reply to a create temporary file.
2217 ****************************************************************************/
2219 void reply_ctemp(struct smb_request *req)
2221 connection_struct *conn = req->conn;
2222 struct smb_filename *smb_fname = NULL;
2230 TALLOC_CTX *ctx = talloc_tos();
2232 START_PROFILE(SMBctemp);
2235 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2239 fattr = SVAL(req->vwv+0, 0);
2240 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2242 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2243 STR_TERMINATE, &status);
2244 if (!NT_STATUS_IS_OK(status)) {
2245 reply_nterror(req, status);
2249 fname = talloc_asprintf(ctx,
2253 fname = talloc_strdup(ctx, "TMXXXXXX");
2257 reply_nterror(req, NT_STATUS_NO_MEMORY);
2261 status = resolve_dfspath(ctx, conn,
2262 req->flags2 & FLAGS2_DFS_PATHNAMES,
2265 if (!NT_STATUS_IS_OK(status)) {
2266 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2267 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2268 ERRSRV, ERRbadpath);
2271 reply_nterror(req, status);
2275 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
2276 if (!NT_STATUS_IS_OK(status)) {
2277 reply_nterror(req, status);
2281 status = get_full_smb_filename(ctx, smb_fname, &fname);
2282 if (!NT_STATUS_IS_OK(status)) {
2283 reply_nterror(req, status);
2287 status = check_name(conn, fname);
2288 if (!NT_STATUS_IS_OK(status)) {
2289 reply_nterror(req, status);
2293 tmpfd = mkstemp(fname);
2295 reply_unixerror(req, ERRDOS, ERRnoaccess);
2299 SET_STAT_INVALID(smb_fname->st);
2300 SMB_VFS_STAT(conn, fname, &smb_fname->st);
2302 /* We should fail if file does not exist. */
2303 status = SMB_VFS_CREATE_FILE(
2306 0, /* root_dir_fid */
2308 0, /* create_file_flags */
2309 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2310 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2311 FILE_OPEN, /* create_disposition*/
2312 0, /* create_options */
2313 fattr, /* file_attributes */
2314 oplock_request, /* oplock_request */
2315 0, /* allocation_size */
2320 &smb_fname->st); /* psbuf */
2322 /* close fd from mkstemp() */
2325 if (!NT_STATUS_IS_OK(status)) {
2326 if (open_was_deferred(req->mid)) {
2327 /* We have re-scheduled this call. */
2330 reply_openerror(req, status);
2334 reply_outbuf(req, 1, 0);
2335 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2337 /* the returned filename is relative to the directory */
2338 s = strrchr_m(fsp->fsp_name, '/');
2346 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2347 thing in the byte section. JRA */
2348 SSVALS(p, 0, -1); /* what is this? not in spec */
2350 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2352 reply_nterror(req, NT_STATUS_NO_MEMORY);
2356 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2357 SCVAL(req->outbuf, smb_flg,
2358 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2361 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2362 SCVAL(req->outbuf, smb_flg,
2363 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2366 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2367 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2368 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2370 TALLOC_FREE(smb_fname);
2371 END_PROFILE(SMBctemp);
2375 /*******************************************************************
2376 Check if a user is allowed to rename a file.
2377 ********************************************************************/
2379 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2380 uint16 dirtype, SMB_STRUCT_STAT *pst)
2384 if (!CAN_WRITE(conn)) {
2385 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2388 fmode = dos_mode(conn, fsp->fsp_name, pst);
2389 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2390 return NT_STATUS_NO_SUCH_FILE;
2393 if (S_ISDIR(pst->st_ex_mode)) {
2394 if (fsp->posix_open) {
2395 return NT_STATUS_OK;
2398 /* If no pathnames are open below this
2399 directory, allow the rename. */
2401 if (file_find_subpath(fsp)) {
2402 return NT_STATUS_ACCESS_DENIED;
2404 return NT_STATUS_OK;
2407 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2408 return NT_STATUS_OK;
2411 return NT_STATUS_ACCESS_DENIED;
2414 /*******************************************************************
2415 * unlink a file with all relevant access checks
2416 *******************************************************************/
2418 static NTSTATUS do_unlink(connection_struct *conn,
2419 struct smb_request *req,
2420 struct smb_filename *smb_fname,
2426 uint32 dirtype_orig = dirtype;
2429 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2431 if (!CAN_WRITE(conn)) {
2432 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2435 status = get_full_smb_filename(smb_fname, smb_fname, &fname);
2436 if (!NT_STATUS_IS_OK(status)) {
2440 if (SMB_VFS_LSTAT(conn, fname, &smb_fname->st) != 0) {
2441 return map_nt_error_from_unix(errno);
2444 fattr = dos_mode(conn, fname, &smb_fname->st);
2446 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2447 dirtype = aDIR|aARCH|aRONLY;
2450 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2452 return NT_STATUS_NO_SUCH_FILE;
2455 if (!dir_check_ftype(conn, fattr, dirtype)) {
2457 return NT_STATUS_FILE_IS_A_DIRECTORY;
2459 return NT_STATUS_NO_SUCH_FILE;
2462 if (dirtype_orig & 0x8000) {
2463 /* These will never be set for POSIX. */
2464 return NT_STATUS_NO_SUCH_FILE;
2468 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2469 return NT_STATUS_FILE_IS_A_DIRECTORY;
2472 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2473 return NT_STATUS_NO_SUCH_FILE;
2476 if (dirtype & 0xFF00) {
2477 /* These will never be set for POSIX. */
2478 return NT_STATUS_NO_SUCH_FILE;
2483 return NT_STATUS_NO_SUCH_FILE;
2486 /* Can't delete a directory. */
2488 return NT_STATUS_FILE_IS_A_DIRECTORY;
2493 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2494 return NT_STATUS_OBJECT_NAME_INVALID;
2495 #endif /* JRATEST */
2497 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2499 On a Windows share, a file with read-only dosmode can be opened with
2500 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2501 fails with NT_STATUS_CANNOT_DELETE error.
2503 This semantic causes a problem that a user can not
2504 rename a file with read-only dosmode on a Samba share
2505 from a Windows command prompt (i.e. cmd.exe, but can rename
2506 from Windows Explorer).
2509 if (!lp_delete_readonly(SNUM(conn))) {
2510 if (fattr & aRONLY) {
2511 return NT_STATUS_CANNOT_DELETE;
2515 /* On open checks the open itself will check the share mode, so
2516 don't do it here as we'll get it wrong. */
2518 status = SMB_VFS_CREATE_FILE
2521 0, /* root_dir_fid */
2523 0, /* create_file_flags */
2524 DELETE_ACCESS, /* access_mask */
2525 FILE_SHARE_NONE, /* share_access */
2526 FILE_OPEN, /* create_disposition*/
2527 FILE_NON_DIRECTORY_FILE, /* create_options */
2528 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2529 0, /* oplock_request */
2530 0, /* allocation_size */
2535 &smb_fname->st); /* psbuf */
2537 if (!NT_STATUS_IS_OK(status)) {
2538 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2539 nt_errstr(status)));
2543 /* The set is across all open files on this dev/inode pair. */
2544 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2545 close_file(req, fsp, NORMAL_CLOSE);
2546 return NT_STATUS_ACCESS_DENIED;
2549 return close_file(req, fsp, NORMAL_CLOSE);
2552 /****************************************************************************
2553 The guts of the unlink command, split out so it may be called by the NT SMB
2555 ****************************************************************************/
2557 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2558 uint32 dirtype, const char *name_in, bool has_wild)
2560 struct smb_filename *smb_fname = NULL;
2561 char *fname_dir = NULL;
2562 char *fname_mask = NULL;
2564 NTSTATUS status = NT_STATUS_OK;
2565 TALLOC_CTX *ctx = talloc_tos();
2567 status = unix_convert(ctx, conn, name_in, &smb_fname,
2568 has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
2569 if (!NT_STATUS_IS_OK(status)) {
2573 /* Split up the directory from the filename/mask. */
2574 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2575 &fname_dir, &fname_mask);
2576 if (!NT_STATUS_IS_OK(status)) {
2581 * We should only check the mangled cache
2582 * here if unix_convert failed. This means
2583 * that the path in 'mask' doesn't exist
2584 * on the file system and so we need to look
2585 * for a possible mangle. This patch from
2586 * Tine Smukavec <valentin.smukavec@hermes.si>.
2589 if (!VALID_STAT(smb_fname->st) &&
2590 mangle_is_mangled(fname_mask, conn->params)) {
2591 char *new_mask = NULL;
2592 mangle_lookup_name_from_8_3(ctx, fname_mask,
2593 &new_mask, conn->params);
2595 TALLOC_FREE(fname_mask);
2596 fname_mask = new_mask;
2603 * Only one file needs to be unlinked. Append the mask back
2604 * onto the directory.
2606 TALLOC_FREE(smb_fname->base_name);
2607 smb_fname->base_name = talloc_asprintf(smb_fname,
2611 if (!smb_fname->base_name) {
2612 status = NT_STATUS_NO_MEMORY;
2616 dirtype = FILE_ATTRIBUTE_NORMAL;
2619 status = check_name(conn, smb_fname->base_name);
2620 if (!NT_STATUS_IS_OK(status)) {
2624 status = do_unlink(conn, req, smb_fname, dirtype);
2625 if (!NT_STATUS_IS_OK(status)) {
2631 struct smb_Dir *dir_hnd = NULL;
2635 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2636 status = NT_STATUS_OBJECT_NAME_INVALID;
2640 if (strequal(fname_mask,"????????.???")) {
2641 TALLOC_FREE(fname_mask);
2642 fname_mask = talloc_strdup(ctx, "*");
2644 status = NT_STATUS_NO_MEMORY;
2649 status = check_name(conn, fname_dir);
2650 if (!NT_STATUS_IS_OK(status)) {
2654 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2656 if (dir_hnd == NULL) {
2657 status = map_nt_error_from_unix(errno);
2661 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2662 the pattern matches against the long name, otherwise the short name
2663 We don't implement this yet XXXX
2666 status = NT_STATUS_NO_SUCH_FILE;
2668 while ((dname = ReadDirName(dir_hnd, &offset,
2670 if (!is_visible_file(conn, fname_dir, dname,
2671 &smb_fname->st, true)) {
2675 /* Quick check for "." and ".." */
2676 if (ISDOT(dname) || ISDOTDOT(dname)) {
2680 if(!mask_match(dname, fname_mask,
2681 conn->case_sensitive)) {
2685 TALLOC_FREE(smb_fname->base_name);
2686 smb_fname->base_name =
2687 talloc_asprintf(smb_fname, "%s/%s",
2690 if (!smb_fname->base_name) {
2691 TALLOC_FREE(dir_hnd);
2692 status = NT_STATUS_NO_MEMORY;
2696 status = check_name(conn, smb_fname->base_name);
2697 if (!NT_STATUS_IS_OK(status)) {
2698 TALLOC_FREE(dir_hnd);
2702 status = do_unlink(conn, req, smb_fname, dirtype);
2703 if (!NT_STATUS_IS_OK(status)) {
2708 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2709 smb_fname->base_name));
2711 TALLOC_FREE(dir_hnd);
2714 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2715 status = map_nt_error_from_unix(errno);
2719 TALLOC_FREE(smb_fname);
2720 TALLOC_FREE(fname_dir);
2721 TALLOC_FREE(fname_mask);
2725 /****************************************************************************
2727 ****************************************************************************/
2729 void reply_unlink(struct smb_request *req)
2731 connection_struct *conn = req->conn;
2735 bool path_contains_wcard = False;
2736 TALLOC_CTX *ctx = talloc_tos();
2738 START_PROFILE(SMBunlink);
2741 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2742 END_PROFILE(SMBunlink);
2746 dirtype = SVAL(req->vwv+0, 0);
2748 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2749 STR_TERMINATE, &status,
2750 &path_contains_wcard);
2751 if (!NT_STATUS_IS_OK(status)) {
2752 reply_nterror(req, status);
2753 END_PROFILE(SMBunlink);
2757 status = resolve_dfspath_wcard(ctx, conn,
2758 req->flags2 & FLAGS2_DFS_PATHNAMES,
2761 &path_contains_wcard);
2762 if (!NT_STATUS_IS_OK(status)) {
2763 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2764 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2765 ERRSRV, ERRbadpath);
2766 END_PROFILE(SMBunlink);
2769 reply_nterror(req, status);
2770 END_PROFILE(SMBunlink);
2774 DEBUG(3,("reply_unlink : %s\n",name));
2776 status = unlink_internals(conn, req, dirtype, name,
2777 path_contains_wcard);
2778 if (!NT_STATUS_IS_OK(status)) {
2779 if (open_was_deferred(req->mid)) {
2780 /* We have re-scheduled this call. */
2781 END_PROFILE(SMBunlink);
2784 reply_nterror(req, status);
2785 END_PROFILE(SMBunlink);
2789 reply_outbuf(req, 0, 0);
2790 END_PROFILE(SMBunlink);
2795 /****************************************************************************
2797 ****************************************************************************/
2799 static void fail_readraw(void)
2801 const char *errstr = talloc_asprintf(talloc_tos(),
2802 "FAIL ! reply_readbraw: socket write fail (%s)",
2807 exit_server_cleanly(errstr);
2810 /****************************************************************************
2811 Fake (read/write) sendfile. Returns -1 on read or write fail.
2812 ****************************************************************************/
2814 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2818 size_t tosend = nread;
2825 bufsize = MIN(nread, 65536);
2827 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2831 while (tosend > 0) {
2835 if (tosend > bufsize) {
2840 ret = read_file(fsp,buf,startpos,cur_read);
2846 /* If we had a short read, fill with zeros. */
2847 if (ret < cur_read) {
2848 memset(buf + ret, '\0', cur_read - ret);
2851 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2856 startpos += cur_read;
2860 return (ssize_t)nread;
2863 #if defined(WITH_SENDFILE)
2864 /****************************************************************************
2865 Deal with the case of sendfile reading less bytes from the file than
2866 requested. Fill with zeros (all we can do).
2867 ****************************************************************************/
2869 static void sendfile_short_send(files_struct *fsp,
2874 #define SHORT_SEND_BUFSIZE 1024
2875 if (nread < headersize) {
2876 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2877 "header for file %s (%s). Terminating\n",
2878 fsp->fsp_name, strerror(errno) ));
2879 exit_server_cleanly("sendfile_short_send failed");
2882 nread -= headersize;
2884 if (nread < smb_maxcnt) {
2885 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2887 exit_server_cleanly("sendfile_short_send: "
2891 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2892 "with zeros !\n", fsp->fsp_name));
2894 while (nread < smb_maxcnt) {
2896 * We asked for the real file size and told sendfile
2897 * to not go beyond the end of the file. But it can
2898 * happen that in between our fstat call and the
2899 * sendfile call the file was truncated. This is very
2900 * bad because we have already announced the larger
2901 * number of bytes to the client.
2903 * The best we can do now is to send 0-bytes, just as
2904 * a read from a hole in a sparse file would do.
2906 * This should happen rarely enough that I don't care
2907 * about efficiency here :-)
2911 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2912 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2913 exit_server_cleanly("sendfile_short_send: "
2914 "write_data failed");
2921 #endif /* defined WITH_SENDFILE */
2923 /****************************************************************************
2924 Return a readbraw error (4 bytes of zero).
2925 ****************************************************************************/
2927 static void reply_readbraw_error(void)
2931 if (write_data(smbd_server_fd(),header,4) != 4) {
2936 /****************************************************************************
2937 Use sendfile in readbraw.
2938 ****************************************************************************/
2940 static void send_file_readbraw(connection_struct *conn,
2941 struct smb_request *req,
2947 char *outbuf = NULL;
2950 #if defined(WITH_SENDFILE)
2952 * We can only use sendfile on a non-chained packet
2953 * but we can use on a non-oplocked file. tridge proved this
2954 * on a train in Germany :-). JRA.
2955 * reply_readbraw has already checked the length.
2958 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2959 (fsp->wcp == NULL) &&
2960 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2961 ssize_t sendfile_read = -1;
2963 DATA_BLOB header_blob;
2965 _smb_setlen(header,nread);
2966 header_blob = data_blob_const(header, 4);
2968 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2969 &header_blob, startpos, nread)) == -1) {
2970 /* Returning ENOSYS means no data at all was sent.
2971 * Do this as a normal read. */
2972 if (errno == ENOSYS) {
2973 goto normal_readbraw;
2977 * Special hack for broken Linux with no working sendfile. If we
2978 * return EINTR we sent the header but not the rest of the data.
2979 * Fake this up by doing read/write calls.
2981 if (errno == EINTR) {
2982 /* Ensure we don't do this again. */
2983 set_use_sendfile(SNUM(conn), False);
2984 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2986 if (fake_sendfile(fsp, startpos, nread) == -1) {
2987 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2988 fsp->fsp_name, strerror(errno) ));
2989 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2994 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2995 fsp->fsp_name, strerror(errno) ));
2996 exit_server_cleanly("send_file_readbraw sendfile failed");
2997 } else if (sendfile_read == 0) {
2999 * Some sendfile implementations return 0 to indicate
3000 * that there was a short read, but nothing was
3001 * actually written to the socket. In this case,
3002 * fallback to the normal read path so the header gets
3003 * the correct byte count.
3005 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3006 "bytes falling back to the normal read: "
3007 "%s\n", fsp->fsp_name));
3008 goto normal_readbraw;
3011 /* Deal with possible short send. */
3012 if (sendfile_read != 4+nread) {
3013 sendfile_short_send(fsp, sendfile_read, 4, nread);
3021 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3023 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3024 (unsigned)(nread+4)));
3025 reply_readbraw_error();
3030 ret = read_file(fsp,outbuf+4,startpos,nread);
3031 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3040 _smb_setlen(outbuf,ret);
3041 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3044 TALLOC_FREE(outbuf);
3047 /****************************************************************************
3048 Reply to a readbraw (core+ protocol).
3049 ****************************************************************************/
3051 void reply_readbraw(struct smb_request *req)
3053 connection_struct *conn = req->conn;
3054 ssize_t maxcount,mincount;
3058 struct lock_struct lock;
3062 START_PROFILE(SMBreadbraw);
3064 if (srv_is_signing_active(smbd_server_conn) ||
3065 is_encrypted_packet(req->inbuf)) {
3066 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3067 "raw reads/writes are disallowed.");
3071 reply_readbraw_error();
3072 END_PROFILE(SMBreadbraw);
3077 * Special check if an oplock break has been issued
3078 * and the readraw request croses on the wire, we must
3079 * return a zero length response here.
3082 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3085 * We have to do a check_fsp by hand here, as
3086 * we must always return 4 zero bytes on error,
3090 if (!fsp || !conn || conn != fsp->conn ||
3091 req->vuid != fsp->vuid ||
3092 fsp->is_directory || fsp->fh->fd == -1) {
3094 * fsp could be NULL here so use the value from the packet. JRA.
3096 DEBUG(3,("reply_readbraw: fnum %d not valid "
3098 (int)SVAL(req->vwv+0, 0)));
3099 reply_readbraw_error();
3100 END_PROFILE(SMBreadbraw);
3104 /* Do a "by hand" version of CHECK_READ. */
3105 if (!(fsp->can_read ||
3106 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3107 (fsp->access_mask & FILE_EXECUTE)))) {
3108 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3109 (int)SVAL(req->vwv+0, 0)));
3110 reply_readbraw_error();
3111 END_PROFILE(SMBreadbraw);
3115 flush_write_cache(fsp, READRAW_FLUSH);
3117 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3118 if(req->wct == 10) {
3120 * This is a large offset (64 bit) read.
3122 #ifdef LARGE_SMB_OFF_T
3124 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3126 #else /* !LARGE_SMB_OFF_T */
3129 * Ensure we haven't been sent a >32 bit offset.
3132 if(IVAL(req->vwv+8, 0) != 0) {
3133 DEBUG(0,("reply_readbraw: large offset "
3134 "(%x << 32) used and we don't support "
3135 "64 bit offsets.\n",
3136 (unsigned int)IVAL(req->vwv+8, 0) ));
3137 reply_readbraw_error();
3138 END_PROFILE(SMBreadbraw);
3142 #endif /* LARGE_SMB_OFF_T */
3145 DEBUG(0,("reply_readbraw: negative 64 bit "
3146 "readraw offset (%.0f) !\n",
3147 (double)startpos ));
3148 reply_readbraw_error();
3149 END_PROFILE(SMBreadbraw);
3154 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3155 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3157 /* ensure we don't overrun the packet size */
3158 maxcount = MIN(65535,maxcount);
3160 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3161 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3164 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3165 reply_readbraw_error();
3166 END_PROFILE(SMBreadbraw);
3170 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3171 size = st.st_ex_size;
3174 if (startpos >= size) {
3177 nread = MIN(maxcount,(size - startpos));
3180 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3181 if (nread < mincount)
3185 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3186 "min=%lu nread=%lu\n",
3187 fsp->fnum, (double)startpos,
3188 (unsigned long)maxcount,
3189 (unsigned long)mincount,
3190 (unsigned long)nread ) );
3192 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3194 DEBUG(5,("reply_readbraw finished\n"));
3196 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3198 END_PROFILE(SMBreadbraw);
3203 #define DBGC_CLASS DBGC_LOCKING
3205 /****************************************************************************
3206 Reply to a lockread (core+ protocol).
3207 ****************************************************************************/
3209 void reply_lockread(struct smb_request *req)
3211 connection_struct *conn = req->conn;
3218 struct byte_range_lock *br_lck = NULL;
3220 struct smbd_server_connection *sconn = smbd_server_conn;
3222 START_PROFILE(SMBlockread);
3225 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3226 END_PROFILE(SMBlockread);
3230 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3232 if (!check_fsp(conn, req, fsp)) {
3233 END_PROFILE(SMBlockread);
3237 if (!CHECK_READ(fsp,req)) {
3238 reply_doserror(req, ERRDOS, ERRbadaccess);
3239 END_PROFILE(SMBlockread);
3243 numtoread = SVAL(req->vwv+1, 0);
3244 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3246 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3248 reply_outbuf(req, 5, numtoread + 3);
3250 data = smb_buf(req->outbuf) + 3;
3253 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3254 * protocol request that predates the read/write lock concept.
3255 * Thus instead of asking for a read lock here we need to ask
3256 * for a write lock. JRA.
3257 * Note that the requested lock size is unaffected by max_recv.
3260 br_lck = do_lock(smbd_messaging_context(),
3263 (uint64_t)numtoread,
3267 False, /* Non-blocking lock. */
3271 TALLOC_FREE(br_lck);
3273 if (NT_STATUS_V(status)) {
3274 reply_nterror(req, status);
3275 END_PROFILE(SMBlockread);
3280 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3283 if (numtoread > sconn->smb1.negprot.max_recv) {
3284 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3285 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3286 (unsigned int)numtoread,
3287 (unsigned int)sconn->smb1.negprot.max_recv));
3288 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3290 nread = read_file(fsp,data,startpos,numtoread);
3293 reply_unixerror(req, ERRDOS, ERRnoaccess);
3294 END_PROFILE(SMBlockread);
3298 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3300 SSVAL(req->outbuf,smb_vwv0,nread);
3301 SSVAL(req->outbuf,smb_vwv5,nread+3);
3302 p = smb_buf(req->outbuf);
3303 SCVAL(p,0,0); /* pad byte. */
3306 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3307 fsp->fnum, (int)numtoread, (int)nread));
3309 END_PROFILE(SMBlockread);
3314 #define DBGC_CLASS DBGC_ALL
3316 /****************************************************************************
3318 ****************************************************************************/
3320 void reply_read(struct smb_request *req)
3322 connection_struct *conn = req->conn;
3329 struct lock_struct lock;
3330 struct smbd_server_connection *sconn = smbd_server_conn;
3332 START_PROFILE(SMBread);
3335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3336 END_PROFILE(SMBread);
3340 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3342 if (!check_fsp(conn, req, fsp)) {
3343 END_PROFILE(SMBread);
3347 if (!CHECK_READ(fsp,req)) {
3348 reply_doserror(req, ERRDOS, ERRbadaccess);
3349 END_PROFILE(SMBread);
3353 numtoread = SVAL(req->vwv+1, 0);
3354 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3356 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3359 * The requested read size cannot be greater than max_recv. JRA.
3361 if (numtoread > sconn->smb1.negprot.max_recv) {
3362 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3363 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3364 (unsigned int)numtoread,
3365 (unsigned int)sconn->smb1.negprot.max_recv));
3366 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3369 reply_outbuf(req, 5, numtoread+3);
3371 data = smb_buf(req->outbuf) + 3;
3373 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3374 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3377 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3378 reply_doserror(req, ERRDOS,ERRlock);
3379 END_PROFILE(SMBread);
3384 nread = read_file(fsp,data,startpos,numtoread);
3387 reply_unixerror(req, ERRDOS,ERRnoaccess);
3391 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3393 SSVAL(req->outbuf,smb_vwv0,nread);
3394 SSVAL(req->outbuf,smb_vwv5,nread+3);
3395 SCVAL(smb_buf(req->outbuf),0,1);
3396 SSVAL(smb_buf(req->outbuf),1,nread);
3398 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3399 fsp->fnum, (int)numtoread, (int)nread ) );
3402 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3404 END_PROFILE(SMBread);
3408 /****************************************************************************
3410 ****************************************************************************/
3412 static int setup_readX_header(struct smb_request *req, char *outbuf,
3418 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3419 data = smb_buf(outbuf);
3421 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3423 SCVAL(outbuf,smb_vwv0,0xFF);
3424 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3425 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3426 SSVAL(outbuf,smb_vwv6,
3428 + 1 /* the wct field */
3429 + 12 * sizeof(uint16_t) /* vwv */
3430 + 2); /* the buflen field */
3431 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3432 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3433 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3434 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3438 /****************************************************************************
3439 Reply to a read and X - possibly using sendfile.
3440 ****************************************************************************/
3442 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3443 files_struct *fsp, SMB_OFF_T startpos,
3446 SMB_STRUCT_STAT sbuf;
3448 struct lock_struct lock;
3450 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3451 reply_unixerror(req, ERRDOS, ERRnoaccess);
3455 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3456 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3459 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3460 reply_doserror(req, ERRDOS, ERRlock);
3464 if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
3465 || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
3467 * We already know that we would do a short read, so don't
3468 * try the sendfile() path.
3470 goto nosendfile_read;
3473 #if defined(WITH_SENDFILE)
3475 * We can only use sendfile on a non-chained packet
3476 * but we can use on a non-oplocked file. tridge proved this
3477 * on a train in Germany :-). JRA.
3480 if (!req_is_in_chain(req) &&
3481 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3482 (fsp->wcp == NULL) &&
3483 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3484 uint8 headerbuf[smb_size + 12 * 2];
3488 * Set up the packet header before send. We
3489 * assume here the sendfile will work (get the
3490 * correct amount of data).
3493 header = data_blob_const(headerbuf, sizeof(headerbuf));
3495 construct_reply_common_req(req, (char *)headerbuf);
3496 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3498 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3499 /* Returning ENOSYS means no data at all was sent.
3500 Do this as a normal read. */
3501 if (errno == ENOSYS) {
3506 * Special hack for broken Linux with no working sendfile. If we
3507 * return EINTR we sent the header but not the rest of the data.
3508 * Fake this up by doing read/write calls.
3511 if (errno == EINTR) {
3512 /* Ensure we don't do this again. */
3513 set_use_sendfile(SNUM(conn), False);
3514 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3515 nread = fake_sendfile(fsp, startpos,
3518 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3519 fsp->fsp_name, strerror(errno) ));
3520 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3522 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3523 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3524 /* No outbuf here means successful sendfile. */
3528 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3529 fsp->fsp_name, strerror(errno) ));
3530 exit_server_cleanly("send_file_readX sendfile failed");
3531 } else if (nread == 0) {
3533 * Some sendfile implementations return 0 to indicate
3534 * that there was a short read, but nothing was
3535 * actually written to the socket. In this case,
3536 * fallback to the normal read path so the header gets
3537 * the correct byte count.
3539 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3540 "falling back to the normal read: %s\n",
3545 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3546 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3548 /* Deal with possible short send. */
3549 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3550 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3552 /* No outbuf here means successful sendfile. */
3553 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3554 SMB_PERFCOUNT_END(&req->pcd);
3562 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3563 uint8 headerbuf[smb_size + 2*12];
3565 construct_reply_common_req(req, (char *)headerbuf);
3566 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3568 /* Send out the header. */
3569 if (write_data(smbd_server_fd(), (char *)headerbuf,
3570 sizeof(headerbuf)) != sizeof(headerbuf)) {
3571 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3572 fsp->fsp_name, strerror(errno) ));
3573 exit_server_cleanly("send_file_readX sendfile failed");
3575 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3577 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3578 fsp->fsp_name, strerror(errno) ));
3579 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3586 reply_outbuf(req, 12, smb_maxcnt);
3588 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3590 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3593 reply_unixerror(req, ERRDOS, ERRnoaccess);
3597 setup_readX_header(req, (char *)req->outbuf, nread);
3599 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3600 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3606 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3607 TALLOC_FREE(req->outbuf);
3611 /****************************************************************************
3612 Reply to a read and X.
3613 ****************************************************************************/
3615 void reply_read_and_X(struct smb_request *req)
3617 connection_struct *conn = req->conn;
3621 bool big_readX = False;
3623 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3626 START_PROFILE(SMBreadX);
3628 if ((req->wct != 10) && (req->wct != 12)) {
3629 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3633 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3634 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3635 smb_maxcnt = SVAL(req->vwv+5, 0);
3637 /* If it's an IPC, pass off the pipe handler. */
3639 reply_pipe_read_and_X(req);
3640 END_PROFILE(SMBreadX);
3644 if (!check_fsp(conn, req, fsp)) {
3645 END_PROFILE(SMBreadX);
3649 if (!CHECK_READ(fsp,req)) {
3650 reply_doserror(req, ERRDOS,ERRbadaccess);
3651 END_PROFILE(SMBreadX);
3655 if (global_client_caps & CAP_LARGE_READX) {
3656 size_t upper_size = SVAL(req->vwv+7, 0);
3657 smb_maxcnt |= (upper_size<<16);
3658 if (upper_size > 1) {
3659 /* Can't do this on a chained packet. */
3660 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3661 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3662 END_PROFILE(SMBreadX);
3665 /* We currently don't do this on signed or sealed data. */
3666 if (srv_is_signing_active(smbd_server_conn) ||
3667 is_encrypted_packet(req->inbuf)) {
3668 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3669 END_PROFILE(SMBreadX);
3672 /* Is there room in the reply for this data ? */
3673 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3675 NT_STATUS_INVALID_PARAMETER);
3676 END_PROFILE(SMBreadX);
3683 if (req->wct == 12) {
3684 #ifdef LARGE_SMB_OFF_T
3686 * This is a large offset (64 bit) read.
3688 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3690 #else /* !LARGE_SMB_OFF_T */
3693 * Ensure we haven't been sent a >32 bit offset.
3696 if(IVAL(req->vwv+10, 0) != 0) {
3697 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3698 "used and we don't support 64 bit offsets.\n",
3699 (unsigned int)IVAL(req->vwv+10, 0) ));
3700 END_PROFILE(SMBreadX);
3701 reply_doserror(req, ERRDOS, ERRbadaccess);
3705 #endif /* LARGE_SMB_OFF_T */
3710 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3714 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3717 END_PROFILE(SMBreadX);
3721 /****************************************************************************
3722 Error replies to writebraw must have smb_wct == 1. Fix this up.
3723 ****************************************************************************/
3725 void error_to_writebrawerr(struct smb_request *req)
3727 uint8 *old_outbuf = req->outbuf;
3729 reply_outbuf(req, 1, 0);
3731 memcpy(req->outbuf, old_outbuf, smb_size);
3732 TALLOC_FREE(old_outbuf);
3735 /****************************************************************************
3736 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3737 ****************************************************************************/
3739 void reply_writebraw(struct smb_request *req)
3741 connection_struct *conn = req->conn;
3744 ssize_t total_written=0;
3745 size_t numtowrite=0;
3751 struct lock_struct lock;
3754 START_PROFILE(SMBwritebraw);
3757 * If we ever reply with an error, it must have the SMB command
3758 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3761 SCVAL(req->inbuf,smb_com,SMBwritec);
3763 if (srv_is_signing_active(smbd_server_conn)) {
3764 END_PROFILE(SMBwritebraw);
3765 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3766 "raw reads/writes are disallowed.");
3769 if (req->wct < 12) {
3770 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3771 error_to_writebrawerr(req);
3772 END_PROFILE(SMBwritebraw);
3776 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3777 if (!check_fsp(conn, req, fsp)) {
3778 error_to_writebrawerr(req);
3779 END_PROFILE(SMBwritebraw);
3783 if (!CHECK_WRITE(fsp)) {
3784 reply_doserror(req, ERRDOS, ERRbadaccess);
3785 error_to_writebrawerr(req);
3786 END_PROFILE(SMBwritebraw);
3790 tcount = IVAL(req->vwv+1, 0);
3791 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3792 write_through = BITSETW(req->vwv+7,0);
3794 /* We have to deal with slightly different formats depending
3795 on whether we are using the core+ or lanman1.0 protocol */
3797 if(Protocol <= PROTOCOL_COREPLUS) {
3798 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3799 data = smb_buf(req->inbuf);
3801 numtowrite = SVAL(req->vwv+10, 0);
3802 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3805 /* Ensure we don't write bytes past the end of this packet. */
3806 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3808 error_to_writebrawerr(req);
3809 END_PROFILE(SMBwritebraw);
3813 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3814 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3817 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3818 reply_doserror(req, ERRDOS, ERRlock);
3819 error_to_writebrawerr(req);
3820 END_PROFILE(SMBwritebraw);
3825 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3828 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3829 "wrote=%d sync=%d\n",
3830 fsp->fnum, (double)startpos, (int)numtowrite,
3831 (int)nwritten, (int)write_through));
3833 if (nwritten < (ssize_t)numtowrite) {
3834 reply_unixerror(req, ERRHRD, ERRdiskfull);
3835 error_to_writebrawerr(req);
3839 total_written = nwritten;
3841 /* Allocate a buffer of 64k + length. */
3842 buf = TALLOC_ARRAY(NULL, char, 65540);
3844 reply_doserror(req, ERRDOS, ERRnomem);
3845 error_to_writebrawerr(req);
3849 /* Return a SMBwritebraw message to the redirector to tell
3850 * it to send more bytes */
3852 memcpy(buf, req->inbuf, smb_size);
3853 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3854 SCVAL(buf,smb_com,SMBwritebraw);
3855 SSVALS(buf,smb_vwv0,0xFFFF);
3857 if (!srv_send_smb(smbd_server_fd(),
3859 false, 0, /* no signing */
3860 IS_CONN_ENCRYPTED(conn),
3862 exit_server_cleanly("reply_writebraw: srv_send_smb "
3866 /* Now read the raw data into the buffer and write it */
3867 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3869 if (!NT_STATUS_IS_OK(status)) {
3870 exit_server_cleanly("secondary writebraw failed");
3873 /* Set up outbuf to return the correct size */
3874 reply_outbuf(req, 1, 0);
3876 if (numtowrite != 0) {
3878 if (numtowrite > 0xFFFF) {
3879 DEBUG(0,("reply_writebraw: Oversize secondary write "
3880 "raw requested (%u). Terminating\n",
3881 (unsigned int)numtowrite ));
3882 exit_server_cleanly("secondary writebraw failed");
3885 if (tcount > nwritten+numtowrite) {
3886 DEBUG(3,("reply_writebraw: Client overestimated the "
3888 (int)tcount,(int)nwritten,(int)numtowrite));
3891 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3893 if (!NT_STATUS_IS_OK(status)) {
3894 DEBUG(0,("reply_writebraw: Oversize secondary write "
3895 "raw read failed (%s). Terminating\n",
3896 nt_errstr(status)));
3897 exit_server_cleanly("secondary writebraw failed");
3900 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3901 if (nwritten == -1) {
3903 reply_unixerror(req, ERRHRD, ERRdiskfull);
3904 error_to_writebrawerr(req);
3908 if (nwritten < (ssize_t)numtowrite) {
3909 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3910 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3914 total_written += nwritten;
3919 SSVAL(req->outbuf,smb_vwv0,total_written);
3921 status = sync_file(conn, fsp, write_through);
3922 if (!NT_STATUS_IS_OK(status)) {
3923 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3924 fsp->fsp_name, nt_errstr(status) ));
3925 reply_nterror(req, status);
3926 error_to_writebrawerr(req);
3930 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3932 fsp->fnum, (double)startpos, (int)numtowrite,
3933 (int)total_written));
3935 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3937 /* We won't return a status if write through is not selected - this
3938 * follows what WfWg does */
3939 END_PROFILE(SMBwritebraw);
3941 if (!write_through && total_written==tcount) {
3943 #if RABBIT_PELLET_FIX
3945 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3946 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3949 if (!send_keepalive(smbd_server_fd())) {
3950 exit_server_cleanly("reply_writebraw: send of "
3951 "keepalive failed");
3954 TALLOC_FREE(req->outbuf);
3959 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3961 END_PROFILE(SMBwritebraw);
3966 #define DBGC_CLASS DBGC_LOCKING
3968 /****************************************************************************
3969 Reply to a writeunlock (core+).
3970 ****************************************************************************/
3972 void reply_writeunlock(struct smb_request *req)
3974 connection_struct *conn = req->conn;
3975 ssize_t nwritten = -1;
3979 NTSTATUS status = NT_STATUS_OK;
3981 struct lock_struct lock;
3983 START_PROFILE(SMBwriteunlock);
3986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3987 END_PROFILE(SMBwriteunlock);
3991 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3993 if (!check_fsp(conn, req, fsp)) {
3994 END_PROFILE(SMBwriteunlock);
3998 if (!CHECK_WRITE(fsp)) {
3999 reply_doserror(req, ERRDOS,ERRbadaccess);
4000 END_PROFILE(SMBwriteunlock);
4004 numtowrite = SVAL(req->vwv+1, 0);
4005 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4006 data = (const char *)req->buf + 3;
4009 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4010 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4013 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4014 reply_doserror(req, ERRDOS, ERRlock);
4015 END_PROFILE(SMBwriteunlock);
4020 /* The special X/Open SMB protocol handling of
4021 zero length writes is *NOT* done for
4023 if(numtowrite == 0) {
4026 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4029 status = sync_file(conn, fsp, False /* write through */);
4030 if (!NT_STATUS_IS_OK(status)) {
4031 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4032 fsp->fsp_name, nt_errstr(status) ));
4033 reply_nterror(req, status);
4037 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
4038 reply_unixerror(req, ERRHRD, ERRdiskfull);
4043 status = do_unlock(smbd_messaging_context(),
4046 (uint64_t)numtowrite,
4050 if (NT_STATUS_V(status)) {
4051 reply_nterror(req, status);
4056 reply_outbuf(req, 1, 0);
4058 SSVAL(req->outbuf,smb_vwv0,nwritten);
4060 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4061 fsp->fnum, (int)numtowrite, (int)nwritten));
4065 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4068 END_PROFILE(SMBwriteunlock);
4073 #define DBGC_CLASS DBGC_ALL
4075 /****************************************************************************
4077 ****************************************************************************/
4079 void reply_write(struct smb_request *req)
4081 connection_struct *conn = req->conn;
4083 ssize_t nwritten = -1;
4087 struct lock_struct lock;
4090 START_PROFILE(SMBwrite);
4093 END_PROFILE(SMBwrite);
4094 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4098 /* If it's an IPC, pass off the pipe handler. */
4100 reply_pipe_write(req);
4101 END_PROFILE(SMBwrite);
4105 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4107 if (!check_fsp(conn, req, fsp)) {
4108 END_PROFILE(SMBwrite);
4112 if (!CHECK_WRITE(fsp)) {
4113 reply_doserror(req, ERRDOS, ERRbadaccess);
4114 END_PROFILE(SMBwrite);
4118 numtowrite = SVAL(req->vwv+1, 0);
4119 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4120 data = (const char *)req->buf + 3;
4122 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4123 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4126 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4127 reply_doserror(req, ERRDOS, ERRlock);
4128 END_PROFILE(SMBwrite);
4133 * X/Open SMB protocol says that if smb_vwv1 is
4134 * zero then the file size should be extended or
4135 * truncated to the size given in smb_vwv[2-3].
4138 if(numtowrite == 0) {
4140 * This is actually an allocate call, and set EOF. JRA.
4142 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4144 reply_nterror(req, NT_STATUS_DISK_FULL);
4147 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4149 reply_nterror(req, NT_STATUS_DISK_FULL);
4152 trigger_write_time_update_immediate(fsp);
4154 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4157 status = sync_file(conn, fsp, False);
4158 if (!NT_STATUS_IS_OK(status)) {
4159 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4160 fsp->fsp_name, nt_errstr(status) ));
4161 reply_nterror(req, status);
4165 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4166 reply_unixerror(req, ERRHRD, ERRdiskfull);
4170 reply_outbuf(req, 1, 0);
4172 SSVAL(req->outbuf,smb_vwv0,nwritten);
4174 if (nwritten < (ssize_t)numtowrite) {
4175 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4176 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4179 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4182 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4184 END_PROFILE(SMBwrite);
4188 /****************************************************************************
4189 Ensure a buffer is a valid writeX for recvfile purposes.
4190 ****************************************************************************/
4192 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4193 (2*14) + /* word count (including bcc) */ \
4196 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4199 connection_struct *conn = NULL;
4200 unsigned int doff = 0;
4201 size_t len = smb_len_large(inbuf);
4202 struct smbd_server_connection *sconn = smbd_server_conn;
4204 if (is_encrypted_packet(inbuf)) {
4205 /* Can't do this on encrypted
4210 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4214 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4215 CVAL(inbuf,smb_wct) != 14) {
4216 DEBUG(10,("is_valid_writeX_buffer: chained or "
4217 "invalid word length.\n"));
4221 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4223 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4227 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4230 if (IS_PRINT(conn)) {
4231 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4234 doff = SVAL(inbuf,smb_vwv11);
4236 numtowrite = SVAL(inbuf,smb_vwv10);
4238 if (len > doff && len - doff > 0xFFFF) {
4239 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4242 if (numtowrite == 0) {
4243 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4247 /* Ensure the sizes match up. */
4248 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4249 /* no pad byte...old smbclient :-( */
4250 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4252 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4256 if (len - doff != numtowrite) {
4257 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4258 "len = %u, doff = %u, numtowrite = %u\n",
4261 (unsigned int)numtowrite ));
4265 DEBUG(10,("is_valid_writeX_buffer: true "
4266 "len = %u, doff = %u, numtowrite = %u\n",
4269 (unsigned int)numtowrite ));
4274 /****************************************************************************
4275 Reply to a write and X.
4276 ****************************************************************************/
4278 void reply_write_and_X(struct smb_request *req)
4280 connection_struct *conn = req->conn;
4282 struct lock_struct lock;
4287 unsigned int smb_doff;
4288 unsigned int smblen;
4292 START_PROFILE(SMBwriteX);
4294 if ((req->wct != 12) && (req->wct != 14)) {
4295 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4296 END_PROFILE(SMBwriteX);
4300 numtowrite = SVAL(req->vwv+10, 0);
4301 smb_doff = SVAL(req->vwv+11, 0);
4302 smblen = smb_len(req->inbuf);
4304 if (req->unread_bytes > 0xFFFF ||
4305 (smblen > smb_doff &&
4306 smblen - smb_doff > 0xFFFF)) {
4307 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4310 if (req->unread_bytes) {
4311 /* Can't do a recvfile write on IPC$ */
4313 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4314 END_PROFILE(SMBwriteX);
4317 if (numtowrite != req->unread_bytes) {
4318 reply_doserror(req, ERRDOS, ERRbadmem);
4319 END_PROFILE(SMBwriteX);
4323 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4324 smb_doff + numtowrite > smblen) {
4325 reply_doserror(req, ERRDOS, ERRbadmem);
4326 END_PROFILE(SMBwriteX);
4331 /* If it's an IPC, pass off the pipe handler. */
4333 if (req->unread_bytes) {
4334 reply_doserror(req, ERRDOS, ERRbadmem);
4335 END_PROFILE(SMBwriteX);
4338 reply_pipe_write_and_X(req);
4339 END_PROFILE(SMBwriteX);
4343 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4344 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4345 write_through = BITSETW(req->vwv+7,0);
4347 if (!check_fsp(conn, req, fsp)) {
4348 END_PROFILE(SMBwriteX);
4352 if (!CHECK_WRITE(fsp)) {
4353 reply_doserror(req, ERRDOS, ERRbadaccess);
4354 END_PROFILE(SMBwriteX);
4358 data = smb_base(req->inbuf) + smb_doff;
4360 if(req->wct == 14) {
4361 #ifdef LARGE_SMB_OFF_T
4363 * This is a large offset (64 bit) write.
4365 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4367 #else /* !LARGE_SMB_OFF_T */
4370 * Ensure we haven't been sent a >32 bit offset.
4373 if(IVAL(req->vwv+12, 0) != 0) {
4374 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4375 "used and we don't support 64 bit offsets.\n",
4376 (unsigned int)IVAL(req->vwv+12, 0) ));
4377 reply_doserror(req, ERRDOS, ERRbadaccess);
4378 END_PROFILE(SMBwriteX);
4382 #endif /* LARGE_SMB_OFF_T */
4385 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4386 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4389 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4390 reply_doserror(req, ERRDOS, ERRlock);
4391 END_PROFILE(SMBwriteX);
4395 /* X/Open SMB protocol says that, unlike SMBwrite
4396 if the length is zero then NO truncation is
4397 done, just a write of zero. To truncate a file,
4400 if(numtowrite == 0) {
4404 if ((req->unread_bytes == 0) &&
4405 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4410 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4413 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4414 reply_unixerror(req, ERRHRD, ERRdiskfull);
4418 reply_outbuf(req, 6, 0);
4419 SSVAL(req->outbuf,smb_vwv2,nwritten);
4420 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4422 if (nwritten < (ssize_t)numtowrite) {
4423 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4424 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4427 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4428 fsp->fnum, (int)numtowrite, (int)nwritten));
4430 status = sync_file(conn, fsp, write_through);
4431 if (!NT_STATUS_IS_OK(status)) {
4432 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4433 fsp->fsp_name, nt_errstr(status) ));
4434 reply_nterror(req, status);
4438 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4440 END_PROFILE(SMBwriteX);
4445 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4447 END_PROFILE(SMBwriteX);
4451 /****************************************************************************
4453 ****************************************************************************/
4455 void reply_lseek(struct smb_request *req)
4457 connection_struct *conn = req->conn;
4463 START_PROFILE(SMBlseek);
4466 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4467 END_PROFILE(SMBlseek);
4471 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4473 if (!check_fsp(conn, req, fsp)) {
4477 flush_write_cache(fsp, SEEK_FLUSH);
4479 mode = SVAL(req->vwv+1, 0) & 3;
4480 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4481 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4490 res = fsp->fh->pos + startpos;
4501 if (umode == SEEK_END) {
4502 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4503 if(errno == EINVAL) {
4504 SMB_OFF_T current_pos = startpos;
4505 SMB_STRUCT_STAT sbuf;
4507 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4508 reply_unixerror(req, ERRDOS,
4510 END_PROFILE(SMBlseek);
4514 current_pos += sbuf.st_ex_size;
4516 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4521 reply_unixerror(req, ERRDOS, ERRnoaccess);
4522 END_PROFILE(SMBlseek);
4529 reply_outbuf(req, 2, 0);
4530 SIVAL(req->outbuf,smb_vwv0,res);
4532 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4533 fsp->fnum, (double)startpos, (double)res, mode));
4535 END_PROFILE(SMBlseek);
4539 /****************************************************************************
4541 ****************************************************************************/
4543 void reply_flush(struct smb_request *req)
4545 connection_struct *conn = req->conn;
4549 START_PROFILE(SMBflush);
4552 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4556 fnum = SVAL(req->vwv+0, 0);
4557 fsp = file_fsp(req, fnum);
4559 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4564 file_sync_all(conn);
4566 NTSTATUS status = sync_file(conn, fsp, True);
4567 if (!NT_STATUS_IS_OK(status)) {
4568 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4569 fsp->fsp_name, nt_errstr(status) ));
4570 reply_nterror(req, status);
4571 END_PROFILE(SMBflush);
4576 reply_outbuf(req, 0, 0);
4578 DEBUG(3,("flush\n"));
4579 END_PROFILE(SMBflush);
4583 /****************************************************************************
4585 conn POINTER CAN BE NULL HERE !
4586 ****************************************************************************/
4588 void reply_exit(struct smb_request *req)
4590 START_PROFILE(SMBexit);
4592 file_close_pid(req->smbpid, req->vuid);
4594 reply_outbuf(req, 0, 0);
4596 DEBUG(3,("exit\n"));
4598 END_PROFILE(SMBexit);
4602 /****************************************************************************
4603 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4604 ****************************************************************************/
4606 void reply_close(struct smb_request *req)
4608 connection_struct *conn = req->conn;
4609 NTSTATUS status = NT_STATUS_OK;
4610 files_struct *fsp = NULL;
4611 START_PROFILE(SMBclose);
4614 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4615 END_PROFILE(SMBclose);
4619 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4622 * We can only use check_fsp if we know it's not a directory.
4625 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4626 reply_doserror(req, ERRDOS, ERRbadfid);
4627 END_PROFILE(SMBclose);
4631 if(fsp->is_directory) {
4633 * Special case - close NT SMB directory handle.
4635 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4636 status = close_file(req, fsp, NORMAL_CLOSE);
4640 * Close ordinary file.
4643 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4644 fsp->fh->fd, fsp->fnum,
4645 conn->num_files_open));
4648 * Take care of any time sent in the close.
4651 t = srv_make_unix_date3(req->vwv+1);
4652 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4655 * close_file() returns the unix errno if an error
4656 * was detected on close - normally this is due to
4657 * a disk full error. If not then it was probably an I/O error.
4660 status = close_file(req, fsp, NORMAL_CLOSE);
4663 if (!NT_STATUS_IS_OK(status)) {
4664 reply_nterror(req, status);
4665 END_PROFILE(SMBclose);
4669 reply_outbuf(req, 0, 0);
4670 END_PROFILE(SMBclose);
4674 /****************************************************************************
4675 Reply to a writeclose (Core+ protocol).
4676 ****************************************************************************/
4678 void reply_writeclose(struct smb_request *req)
4680 connection_struct *conn = req->conn;
4682 ssize_t nwritten = -1;
4683 NTSTATUS close_status = NT_STATUS_OK;
4686 struct timespec mtime;
4688 struct lock_struct lock;
4690 START_PROFILE(SMBwriteclose);
4693 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4694 END_PROFILE(SMBwriteclose);
4698 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4700 if (!check_fsp(conn, req, fsp)) {
4701 END_PROFILE(SMBwriteclose);
4704 if (!CHECK_WRITE(fsp)) {
4705 reply_doserror(req, ERRDOS,ERRbadaccess);
4706 END_PROFILE(SMBwriteclose);
4710 numtowrite = SVAL(req->vwv+1, 0);
4711 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4712 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4713 data = (const char *)req->buf + 1;
4716 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4717 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4720 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4721 reply_doserror(req, ERRDOS,ERRlock);
4722 END_PROFILE(SMBwriteclose);
4727 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4729 set_close_write_time(fsp, mtime);
4732 * More insanity. W2K only closes the file if writelen > 0.
4737 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4739 close_status = close_file(req, fsp, NORMAL_CLOSE);
4742 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4743 fsp->fnum, (int)numtowrite, (int)nwritten,
4744 conn->num_files_open));
4746 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4747 reply_doserror(req, ERRHRD, ERRdiskfull);
4751 if(!NT_STATUS_IS_OK(close_status)) {
4752 reply_nterror(req, close_status);
4756 reply_outbuf(req, 1, 0);
4758 SSVAL(req->outbuf,smb_vwv0,nwritten);
4762 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4765 END_PROFILE(SMBwriteclose);
4770 #define DBGC_CLASS DBGC_LOCKING
4772 /****************************************************************************
4774 ****************************************************************************/
4776 void reply_lock(struct smb_request *req)
4778 connection_struct *conn = req->conn;
4779 uint64_t count,offset;
4782 struct byte_range_lock *br_lck = NULL;
4784 START_PROFILE(SMBlock);
4787 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4788 END_PROFILE(SMBlock);
4792 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4794 if (!check_fsp(conn, req, fsp)) {
4795 END_PROFILE(SMBlock);
4799 count = (uint64_t)IVAL(req->vwv+1, 0);
4800 offset = (uint64_t)IVAL(req->vwv+3, 0);
4802 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4803 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4805 br_lck = do_lock(smbd_messaging_context(),
4812 False, /* Non-blocking lock. */
4817 TALLOC_FREE(br_lck);
4819 if (NT_STATUS_V(status)) {
4820 reply_nterror(req, status);
4821 END_PROFILE(SMBlock);
4825 reply_outbuf(req, 0, 0);
4827 END_PROFILE(SMBlock);
4831 /****************************************************************************
4833 ****************************************************************************/
4835 void reply_unlock(struct smb_request *req)
4837 connection_struct *conn = req->conn;
4838 uint64_t count,offset;
4842 START_PROFILE(SMBunlock);
4845 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4846 END_PROFILE(SMBunlock);
4850 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4852 if (!check_fsp(conn, req, fsp)) {
4853 END_PROFILE(SMBunlock);
4857 count = (uint64_t)IVAL(req->vwv+1, 0);
4858 offset = (uint64_t)IVAL(req->vwv+3, 0);
4860 status = do_unlock(smbd_messaging_context(),
4867 if (NT_STATUS_V(status)) {
4868 reply_nterror(req, status);
4869 END_PROFILE(SMBunlock);
4873 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4874 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4876 reply_outbuf(req, 0, 0);
4878 END_PROFILE(SMBunlock);
4883 #define DBGC_CLASS DBGC_ALL
4885 /****************************************************************************
4887 conn POINTER CAN BE NULL HERE !
4888 ****************************************************************************/
4890 void reply_tdis(struct smb_request *req)
4892 struct smbd_server_connection *sconn = smbd_server_conn;
4893 connection_struct *conn = req->conn;
4894 START_PROFILE(SMBtdis);
4897 DEBUG(4,("Invalid connection in tdis\n"));
4898 reply_doserror(req, ERRSRV, ERRinvnid);
4899 END_PROFILE(SMBtdis);
4905 close_cnum(sconn, conn,req->vuid);
4908 reply_outbuf(req, 0, 0);
4909 END_PROFILE(SMBtdis);
4913 /****************************************************************************
4915 conn POINTER CAN BE NULL HERE !
4916 ****************************************************************************/
4918 void reply_echo(struct smb_request *req)
4920 connection_struct *conn = req->conn;
4921 struct smb_perfcount_data local_pcd;
4922 struct smb_perfcount_data *cur_pcd;
4926 START_PROFILE(SMBecho);
4928 smb_init_perfcount_data(&local_pcd);
4931 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4932 END_PROFILE(SMBecho);
4936 smb_reverb = SVAL(req->vwv+0, 0);
4938 reply_outbuf(req, 1, req->buflen);
4940 /* copy any incoming data back out */
4941 if (req->buflen > 0) {
4942 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4945 if (smb_reverb > 100) {
4946 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4950 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4952 /* this makes sure we catch the request pcd */
4953 if (seq_num == smb_reverb) {
4954 cur_pcd = &req->pcd;
4956 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4957 cur_pcd = &local_pcd;
4960 SSVAL(req->outbuf,smb_vwv0,seq_num);
4962 show_msg((char *)req->outbuf);
4963 if (!srv_send_smb(smbd_server_fd(),
4964 (char *)req->outbuf,
4965 true, req->seqnum+1,
4966 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4968 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4971 DEBUG(3,("echo %d times\n", smb_reverb));
4973 TALLOC_FREE(req->outbuf);
4975 END_PROFILE(SMBecho);
4979 /****************************************************************************
4980 Reply to a printopen.
4981 ****************************************************************************/
4983 void reply_printopen(struct smb_request *req)
4985 connection_struct *conn = req->conn;
4987 SMB_STRUCT_STAT sbuf;
4990 START_PROFILE(SMBsplopen);
4993 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4994 END_PROFILE(SMBsplopen);
4998 if (!CAN_PRINT(conn)) {
4999 reply_doserror(req, ERRDOS, ERRnoaccess);
5000 END_PROFILE(SMBsplopen);
5004 status = file_new(req, conn, &fsp);
5005 if(!NT_STATUS_IS_OK(status)) {
5006 reply_nterror(req, status);
5007 END_PROFILE(SMBsplopen);
5011 /* Open for exclusive use, write only. */
5012 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
5014 if (!NT_STATUS_IS_OK(status)) {
5015 file_free(req, fsp);
5016 reply_nterror(req, status);
5017 END_PROFILE(SMBsplopen);
5021 reply_outbuf(req, 1, 0);
5022 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5024 DEBUG(3,("openprint fd=%d fnum=%d\n",
5025 fsp->fh->fd, fsp->fnum));
5027 END_PROFILE(SMBsplopen);
5031 /****************************************************************************
5032 Reply to a printclose.
5033 ****************************************************************************/
5035 void reply_printclose(struct smb_request *req)
5037 connection_struct *conn = req->conn;
5041 START_PROFILE(SMBsplclose);
5044 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5045 END_PROFILE(SMBsplclose);
5049 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5051 if (!check_fsp(conn, req, fsp)) {
5052 END_PROFILE(SMBsplclose);
5056 if (!CAN_PRINT(conn)) {
5057 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
5058 END_PROFILE(SMBsplclose);
5062 DEBUG(3,("printclose fd=%d fnum=%d\n",
5063 fsp->fh->fd,fsp->fnum));
5065 status = close_file(req, fsp, NORMAL_CLOSE);
5067 if(!NT_STATUS_IS_OK(status)) {
5068 reply_nterror(req, status);
5069 END_PROFILE(SMBsplclose);
5073 reply_outbuf(req, 0, 0);
5075 END_PROFILE(SMBsplclose);
5079 /****************************************************************************
5080 Reply to a printqueue.
5081 ****************************************************************************/
5083 void reply_printqueue(struct smb_request *req)
5085 connection_struct *conn = req->conn;
5089 START_PROFILE(SMBsplretq);
5092 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5093 END_PROFILE(SMBsplretq);
5097 max_count = SVAL(req->vwv+0, 0);
5098 start_index = SVAL(req->vwv+1, 0);
5100 /* we used to allow the client to get the cnum wrong, but that
5101 is really quite gross and only worked when there was only
5102 one printer - I think we should now only accept it if they
5103 get it right (tridge) */
5104 if (!CAN_PRINT(conn)) {
5105 reply_doserror(req, ERRDOS, ERRnoaccess);
5106 END_PROFILE(SMBsplretq);
5110 reply_outbuf(req, 2, 3);
5111 SSVAL(req->outbuf,smb_vwv0,0);
5112 SSVAL(req->outbuf,smb_vwv1,0);
5113 SCVAL(smb_buf(req->outbuf),0,1);
5114 SSVAL(smb_buf(req->outbuf),1,0);
5116 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5117 start_index, max_count));
5120 print_queue_struct *queue = NULL;
5121 print_status_struct status;
5122 int count = print_queue_status(SNUM(conn), &queue, &status);
5123 int num_to_get = ABS(max_count);
5124 int first = (max_count>0?start_index:start_index+max_count+1);
5130 num_to_get = MIN(num_to_get,count-first);
5133 for (i=first;i<first+num_to_get;i++) {
5137 srv_put_dos_date2(p,0,queue[i].time);
5138 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5139 SSVAL(p,5, queue[i].job);
5140 SIVAL(p,7,queue[i].size);
5142 srvstr_push(blob, req->flags2, p+12,
5143 queue[i].fs_user, 16, STR_ASCII);
5145 if (message_push_blob(
5148 blob, sizeof(blob))) == -1) {
5149 reply_nterror(req, NT_STATUS_NO_MEMORY);
5150 END_PROFILE(SMBsplretq);
5156 SSVAL(req->outbuf,smb_vwv0,count);
5157 SSVAL(req->outbuf,smb_vwv1,
5158 (max_count>0?first+count:first-1));
5159 SCVAL(smb_buf(req->outbuf),0,1);
5160 SSVAL(smb_buf(req->outbuf),1,28*count);
5165 DEBUG(3,("%d entries returned in queue\n",count));
5168 END_PROFILE(SMBsplretq);
5172 /****************************************************************************
5173 Reply to a printwrite.
5174 ****************************************************************************/
5176 void reply_printwrite(struct smb_request *req)
5178 connection_struct *conn = req->conn;
5183 START_PROFILE(SMBsplwr);
5186 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5187 END_PROFILE(SMBsplwr);
5191 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5193 if (!check_fsp(conn, req, fsp)) {
5194 END_PROFILE(SMBsplwr);
5198 if (!CAN_PRINT(conn)) {
5199 reply_doserror(req, ERRDOS, ERRnoaccess);
5200 END_PROFILE(SMBsplwr);
5204 if (!CHECK_WRITE(fsp)) {
5205 reply_doserror(req, ERRDOS, ERRbadaccess);
5206 END_PROFILE(SMBsplwr);
5210 numtowrite = SVAL(req->buf, 1);
5212 if (req->buflen < numtowrite + 3) {
5213 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5214 END_PROFILE(SMBsplwr);
5218 data = (const char *)req->buf + 3;
5220 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5221 reply_unixerror(req, ERRHRD, ERRdiskfull);
5222 END_PROFILE(SMBsplwr);
5226 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5228 END_PROFILE(SMBsplwr);
5232 /****************************************************************************
5234 ****************************************************************************/
5236 void reply_mkdir(struct smb_request *req)
5238 connection_struct *conn = req->conn;
5239 struct smb_filename *smb_dname = NULL;
5240 char *directory = NULL;
5242 TALLOC_CTX *ctx = talloc_tos();
5244 START_PROFILE(SMBmkdir);
5246 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5247 STR_TERMINATE, &status);
5248 if (!NT_STATUS_IS_OK(status)) {
5249 reply_nterror(req, status);
5253 status = resolve_dfspath(ctx, conn,
5254 req->flags2 & FLAGS2_DFS_PATHNAMES,
5257 if (!NT_STATUS_IS_OK(status)) {
5258 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5259 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5260 ERRSRV, ERRbadpath);
5263 reply_nterror(req, status);
5267 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
5268 if (!NT_STATUS_IS_OK(status)) {
5269 reply_nterror(req, status);
5273 status = check_name(conn, smb_dname->base_name);
5274 if (!NT_STATUS_IS_OK(status)) {
5275 reply_nterror(req, status);
5279 status = create_directory(conn, req, smb_dname);
5281 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5283 if (!NT_STATUS_IS_OK(status)) {
5285 if (!use_nt_status()
5286 && NT_STATUS_EQUAL(status,
5287 NT_STATUS_OBJECT_NAME_COLLISION)) {
5289 * Yes, in the DOS error code case we get a
5290 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5291 * samba4 torture test.
5293 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5296 reply_nterror(req, status);
5300 reply_outbuf(req, 0, 0);
5302 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5304 TALLOC_FREE(smb_dname);
5305 END_PROFILE(SMBmkdir);
5309 /****************************************************************************
5310 Static function used by reply_rmdir to delete an entire directory
5311 tree recursively. Return True on ok, False on fail.
5312 ****************************************************************************/
5314 static bool recursive_rmdir(TALLOC_CTX *ctx,
5315 connection_struct *conn,
5318 const char *dname = NULL;
5322 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5328 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5329 char *fullname = NULL;
5331 if (ISDOT(dname) || ISDOTDOT(dname)) {
5335 if (!is_visible_file(conn, directory, dname, &st, False)) {
5339 /* Construct the full name. */
5340 fullname = talloc_asprintf(ctx,
5350 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5355 if(st.st_ex_mode & S_IFDIR) {
5356 if(!recursive_rmdir(ctx, conn, fullname)) {
5360 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5364 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5368 TALLOC_FREE(fullname);
5370 TALLOC_FREE(dir_hnd);
5374 /****************************************************************************
5375 The internals of the rmdir code - called elsewhere.
5376 ****************************************************************************/
5378 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5379 connection_struct *conn,
5380 const char *directory)
5385 /* Might be a symlink. */
5386 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5387 return map_nt_error_from_unix(errno);
5390 if (S_ISLNK(st.st_ex_mode)) {
5391 /* Is what it points to a directory ? */
5392 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5393 return map_nt_error_from_unix(errno);
5395 if (!(S_ISDIR(st.st_ex_mode))) {
5396 return NT_STATUS_NOT_A_DIRECTORY;
5398 ret = SMB_VFS_UNLINK(conn,directory);
5400 ret = SMB_VFS_RMDIR(conn,directory);
5403 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5404 FILE_NOTIFY_CHANGE_DIR_NAME,
5406 return NT_STATUS_OK;
5409 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5411 * Check to see if the only thing in this directory are
5412 * vetoed files/directories. If so then delete them and
5413 * retry. If we fail to delete any of them (and we *don't*
5414 * do a recursive delete) then fail the rmdir.
5418 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5419 directory, NULL, 0);
5421 if(dir_hnd == NULL) {
5426 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5427 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5429 if (!is_visible_file(conn, directory, dname, &st, False))
5431 if(!IS_VETO_PATH(conn, dname)) {
5432 TALLOC_FREE(dir_hnd);
5438 /* We only have veto files/directories.
5439 * Are we allowed to delete them ? */
5441 if(!lp_recursive_veto_delete(SNUM(conn))) {
5442 TALLOC_FREE(dir_hnd);
5447 /* Do a recursive delete. */
5448 RewindDir(dir_hnd,&dirpos);
5449 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5450 char *fullname = NULL;
5452 if (ISDOT(dname) || ISDOTDOT(dname)) {
5455 if (!is_visible_file(conn, directory, dname, &st, False)) {
5459 fullname = talloc_asprintf(ctx,
5469 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5472 if(st.st_ex_mode & S_IFDIR) {
5473 if(!recursive_rmdir(ctx, conn, fullname)) {
5476 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5479 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5482 TALLOC_FREE(fullname);
5484 TALLOC_FREE(dir_hnd);
5485 /* Retry the rmdir */
5486 ret = SMB_VFS_RMDIR(conn,directory);
5492 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5493 "%s\n", directory,strerror(errno)));
5494 return map_nt_error_from_unix(errno);
5497 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5498 FILE_NOTIFY_CHANGE_DIR_NAME,
5501 return NT_STATUS_OK;
5504 /****************************************************************************
5506 ****************************************************************************/
5508 void reply_rmdir(struct smb_request *req)
5510 connection_struct *conn = req->conn;
5511 struct smb_filename *smb_dname = NULL;
5512 char *directory = NULL;
5514 TALLOC_CTX *ctx = talloc_tos();
5516 START_PROFILE(SMBrmdir);
5518 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5519 STR_TERMINATE, &status);
5520 if (!NT_STATUS_IS_OK(status)) {
5521 reply_nterror(req, status);
5525 status = resolve_dfspath(ctx, conn,
5526 req->flags2 & FLAGS2_DFS_PATHNAMES,
5529 if (!NT_STATUS_IS_OK(status)) {
5530 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5531 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5532 ERRSRV, ERRbadpath);
5535 reply_nterror(req, status);
5539 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
5540 if (!NT_STATUS_IS_OK(status)) {
5541 reply_nterror(req, status);
5545 status = get_full_smb_filename(ctx, smb_dname, &directory);
5546 if (!NT_STATUS_IS_OK(status)) {
5547 reply_nterror(req, status);
5551 status = check_name(conn, directory);
5552 if (!NT_STATUS_IS_OK(status)) {
5553 reply_nterror(req, status);
5557 dptr_closepath(directory, req->smbpid);
5558 status = rmdir_internals(ctx, conn, directory);
5559 if (!NT_STATUS_IS_OK(status)) {
5560 reply_nterror(req, status);
5564 reply_outbuf(req, 0, 0);
5566 DEBUG( 3, ( "rmdir %s\n", directory ) );
5568 TALLOC_FREE(smb_dname);
5569 END_PROFILE(SMBrmdir);
5573 /*******************************************************************
5574 Resolve wildcards in a filename rename.
5575 ********************************************************************/
5577 static bool resolve_wildcards(TALLOC_CTX *ctx,
5582 char *name2_copy = NULL;
5587 char *p,*p2, *pname1, *pname2;
5589 name2_copy = talloc_strdup(ctx, name2);
5594 pname1 = strrchr_m(name1,'/');
5595 pname2 = strrchr_m(name2_copy,'/');
5597 if (!pname1 || !pname2) {
5601 /* Truncate the copy of name2 at the last '/' */
5604 /* Now go past the '/' */
5608 root1 = talloc_strdup(ctx, pname1);
5609 root2 = talloc_strdup(ctx, pname2);
5611 if (!root1 || !root2) {
5615 p = strrchr_m(root1,'.');
5618 ext1 = talloc_strdup(ctx, p+1);
5620 ext1 = talloc_strdup(ctx, "");
5622 p = strrchr_m(root2,'.');
5625 ext2 = talloc_strdup(ctx, p+1);
5627 ext2 = talloc_strdup(ctx, "");
5630 if (!ext1 || !ext2) {
5638 /* Hmmm. Should this be mb-aware ? */
5641 } else if (*p2 == '*') {
5643 root2 = talloc_asprintf(ctx, "%s%s",
5662 /* Hmmm. Should this be mb-aware ? */
5665 } else if (*p2 == '*') {
5667 ext2 = talloc_asprintf(ctx, "%s%s",
5683 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5688 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5700 /****************************************************************************
5701 Ensure open files have their names updated. Updated to notify other smbd's
5703 ****************************************************************************/
5705 static void rename_open_files(connection_struct *conn,
5706 struct share_mode_lock *lck,
5707 const char *newname)
5710 bool did_rename = False;
5712 for(fsp = file_find_di_first(lck->id); fsp;
5713 fsp = file_find_di_next(fsp)) {
5714 /* fsp_name is a relative path under the fsp. To change this for other
5715 sharepaths we need to manipulate relative paths. */
5716 /* TODO - create the absolute path and manipulate the newname
5717 relative to the sharepath. */
5718 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5721 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5722 fsp->fnum, file_id_string_tos(&fsp->file_id),
5723 fsp->fsp_name, newname ));
5724 string_set(&fsp->fsp_name, newname);
5729 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5730 file_id_string_tos(&lck->id), newname ));
5733 /* Send messages to all smbd's (not ourself) that the name has changed. */
5734 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5738 /****************************************************************************
5739 We need to check if the source path is a parent directory of the destination
5740 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5741 refuse the rename with a sharing violation. Under UNIX the above call can
5742 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5743 probably need to check that the client is a Windows one before disallowing
5744 this as a UNIX client (one with UNIX extensions) can know the source is a
5745 symlink and make this decision intelligently. Found by an excellent bug
5746 report from <AndyLiebman@aol.com>.
5747 ****************************************************************************/
5749 static bool rename_path_prefix_equal(const char *src, const char *dest)
5751 const char *psrc = src;
5752 const char *pdst = dest;
5755 if (psrc[0] == '.' && psrc[1] == '/') {
5758 if (pdst[0] == '.' && pdst[1] == '/') {
5761 if ((slen = strlen(psrc)) > strlen(pdst)) {
5764 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5768 * Do the notify calls from a rename
5771 static void notify_rename(connection_struct *conn, bool is_dir,
5772 const char *oldpath, const char *newpath)
5774 char *olddir, *newdir;
5775 const char *oldname, *newname;
5778 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5779 : FILE_NOTIFY_CHANGE_FILE_NAME;
5781 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5782 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5783 TALLOC_FREE(olddir);
5787 if (strcmp(olddir, newdir) == 0) {
5788 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5789 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5792 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5793 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5795 TALLOC_FREE(olddir);
5796 TALLOC_FREE(newdir);
5798 /* this is a strange one. w2k3 gives an additional event for
5799 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5800 files, but not directories */
5802 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5803 FILE_NOTIFY_CHANGE_ATTRIBUTES
5804 |FILE_NOTIFY_CHANGE_CREATION,
5809 /****************************************************************************
5810 Rename an open file - given an fsp.
5811 ****************************************************************************/
5813 NTSTATUS rename_internals_fsp(connection_struct *conn,
5816 const char *newname_last_component,
5818 bool replace_if_exists)
5820 TALLOC_CTX *ctx = talloc_tos();
5821 SMB_STRUCT_STAT sbuf, sbuf1;
5822 NTSTATUS status = NT_STATUS_OK;
5823 struct share_mode_lock *lck = NULL;
5824 bool dst_exists, old_is_stream, new_is_stream;
5828 status = check_name(conn, newname);
5829 if (!NT_STATUS_IS_OK(status)) {
5833 /* Ensure newname contains a '/' */
5834 if(strrchr_m(newname,'/') == 0) {
5835 newname = talloc_asprintf(ctx,
5839 return NT_STATUS_NO_MEMORY;
5844 * Check for special case with case preserving and not
5845 * case sensitive. If the old last component differs from the original
5846 * last component only by case, then we should allow
5847 * the rename (user is trying to change the case of the
5851 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5852 strequal(newname, fsp->fsp_name)) {
5854 char *newname_modified_last_component = NULL;
5857 * Get the last component of the modified name.
5858 * Note that we guarantee that newname contains a '/'
5861 p = strrchr_m(newname,'/');
5862 newname_modified_last_component = talloc_strdup(ctx,
5864 if (!newname_modified_last_component) {
5865 return NT_STATUS_NO_MEMORY;
5868 if(strcsequal(newname_modified_last_component,
5869 newname_last_component) == False) {
5871 * Replace the modified last component with
5874 *p = '\0'; /* Truncate at the '/' */
5875 newname = talloc_asprintf(ctx,
5878 newname_last_component);
5883 * If the src and dest names are identical - including case,
5884 * don't do the rename, just return success.
5887 if (strcsequal(fsp->fsp_name, newname)) {
5888 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5890 return NT_STATUS_OK;
5893 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5894 new_is_stream = is_ntfs_stream_name(newname);
5896 /* Return the correct error code if both names aren't streams. */
5897 if (!old_is_stream && new_is_stream) {
5898 return NT_STATUS_OBJECT_NAME_INVALID;
5901 if (old_is_stream && !new_is_stream) {
5902 return NT_STATUS_INVALID_PARAMETER;
5906 * Have vfs_object_exist also fill sbuf1
5908 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5910 if(!replace_if_exists && dst_exists) {
5911 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5912 fsp->fsp_name,newname));
5913 return NT_STATUS_OBJECT_NAME_COLLISION;
5917 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5918 files_struct *dst_fsp = file_find_di_first(fileid);
5919 /* The file can be open when renaming a stream */
5920 if (dst_fsp && !new_is_stream) {
5921 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5922 return NT_STATUS_ACCESS_DENIED;
5926 /* Ensure we have a valid stat struct for the source. */
5927 if (fsp->fh->fd != -1) {
5928 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5929 return map_nt_error_from_unix(errno);
5933 if (fsp->posix_open) {
5934 ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
5936 ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
5939 return map_nt_error_from_unix(errno);
5943 status = can_rename(conn, fsp, attrs, &sbuf);
5945 if (!NT_STATUS_IS_OK(status)) {
5946 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5947 nt_errstr(status), fsp->fsp_name,newname));
5948 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5949 status = NT_STATUS_ACCESS_DENIED;
5953 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5954 return NT_STATUS_ACCESS_DENIED;
5957 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5961 * We have the file open ourselves, so not being able to get the
5962 * corresponding share mode lock is a fatal error.
5965 SMB_ASSERT(lck != NULL);
5967 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5968 uint32 create_options = fsp->fh->private_options;
5970 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5971 fsp->fsp_name,newname));
5973 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5975 rename_open_files(conn, lck, newname);
5978 * A rename acts as a new file create w.r.t. allowing an initial delete
5979 * on close, probably because in Windows there is a new handle to the
5980 * new file. If initial delete on close was requested but not
5981 * originally set, we need to set it here. This is probably not 100% correct,
5982 * but will work for the CIFSFS client which in non-posix mode
5983 * depends on these semantics. JRA.
5986 if (create_options & FILE_DELETE_ON_CLOSE) {
5987 status = can_set_delete_on_close(fsp, True, 0);
5989 if (NT_STATUS_IS_OK(status)) {
5990 /* Note that here we set the *inital* delete on close flag,
5991 * not the regular one. The magic gets handled in close. */
5992 fsp->initial_delete_on_close = True;
5996 return NT_STATUS_OK;
6001 if (errno == ENOTDIR || errno == EISDIR) {
6002 status = NT_STATUS_OBJECT_NAME_COLLISION;
6004 status = map_nt_error_from_unix(errno);
6007 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
6008 nt_errstr(status), fsp->fsp_name,newname));
6013 /****************************************************************************
6014 The guts of the rename command, split out so it may be called by the NT SMB
6016 ****************************************************************************/
6018 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6019 connection_struct *conn,
6020 struct smb_request *req,
6021 const char *name_in,
6022 const char *newname_in,
6024 bool replace_if_exists,
6027 uint32_t access_mask)
6029 struct smb_filename *smb_fname = NULL;
6030 struct smb_filename *smb_fname_new = NULL;
6031 char *directory = NULL;
6034 char *newname = NULL;
6037 NTSTATUS status = NT_STATUS_OK;
6038 struct smb_Dir *dir_hnd = NULL;
6041 int create_options = 0;
6042 bool posix_pathnames = lp_posix_pathnames();
6044 status = unix_convert(ctx, conn, name_in, &smb_fname,
6045 src_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6046 if (!NT_STATUS_IS_OK(status)) {
6050 status = get_full_smb_filename(ctx, smb_fname, &name);
6051 if (!NT_STATUS_IS_OK(status)) {
6055 status = unix_convert(ctx, conn, newname_in, &smb_fname_new,
6057 (dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0)));
6058 if (!NT_STATUS_IS_OK(status)) {
6062 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
6063 if (!NT_STATUS_IS_OK(status)) {
6068 * Split the old name into directory and last component
6069 * strings. Note that unix_convert may have stripped off a
6070 * leading ./ from both name and newname if the rename is
6071 * at the root of the share. We need to make sure either both
6072 * name and newname contain a / character or neither of them do
6073 * as this is checked in resolve_wildcards().
6076 p = strrchr_m(name,'/');
6078 directory = talloc_strdup(ctx, ".");
6080 status = NT_STATUS_NO_MEMORY;
6086 directory = talloc_strdup(ctx, name);
6088 status = NT_STATUS_NO_MEMORY;
6092 *p = '/'; /* Replace needed for exceptional test below. */
6096 * We should only check the mangled cache
6097 * here if unix_convert failed. This means
6098 * that the path in 'mask' doesn't exist
6099 * on the file system and so we need to look
6100 * for a possible mangle. This patch from
6101 * Tine Smukavec <valentin.smukavec@hermes.si>.
6104 if (!VALID_STAT(smb_fname->st) && mangle_is_mangled(mask, conn->params)) {
6105 char *new_mask = NULL;
6106 mangle_lookup_name_from_8_3(ctx,
6115 if (!src_has_wild) {
6119 * No wildcards - just process the one file.
6121 /* Add a terminating '/' to the directory name. */
6122 directory = talloc_asprintf_append(directory,
6126 status = NT_STATUS_NO_MEMORY;
6130 /* Ensure newname contains a '/' also */
6131 if(strrchr_m(newname,'/') == 0) {
6132 newname = talloc_asprintf(ctx,
6136 status = NT_STATUS_NO_MEMORY;
6141 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6142 "case_preserve = %d, short case preserve = %d, "
6143 "directory = %s, newname = %s, "
6144 "last_component_dest = %s\n",
6145 conn->case_sensitive, conn->case_preserve,
6146 conn->short_case_preserve, directory,
6147 newname, smb_fname_new->original_lcomp));
6149 /* The dest name still may have wildcards. */
6150 if (dest_has_wild) {
6151 char *mod_newname = NULL;
6152 if (!resolve_wildcards(ctx,
6153 directory,newname,&mod_newname)) {
6154 DEBUG(6, ("rename_internals: resolve_wildcards "
6158 status = NT_STATUS_NO_MEMORY;
6161 newname = mod_newname;
6164 ZERO_STRUCT(smb_fname->st);
6165 if (posix_pathnames) {
6166 SMB_VFS_LSTAT(conn, directory, &smb_fname->st);
6168 SMB_VFS_STAT(conn, directory, &smb_fname->st);
6171 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6172 create_options |= FILE_DIRECTORY_FILE;
6175 status = SMB_VFS_CREATE_FILE(
6178 0, /* root_dir_fid */
6179 directory, /* fname */
6180 0, /* create_file_flags */
6181 access_mask, /* access_mask */
6182 (FILE_SHARE_READ | /* share_access */
6184 FILE_OPEN, /* create_disposition*/
6185 create_options, /* create_options */
6186 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6187 0, /* oplock_request */
6188 0, /* allocation_size */
6193 &smb_fname->st); /* psbuf */
6195 if (!NT_STATUS_IS_OK(status)) {
6196 DEBUG(3, ("Could not open rename source %s: %s\n",
6197 directory, nt_errstr(status)));
6201 status = rename_internals_fsp(conn, fsp, newname,
6202 smb_fname_new->original_lcomp,
6203 attrs, replace_if_exists);
6205 close_file(req, fsp, NORMAL_CLOSE);
6207 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6208 nt_errstr(status), directory,newname));
6214 * Wildcards - process each file that matches.
6216 if (strequal(mask,"????????.???")) {
6221 status = check_name(conn, directory);
6222 if (!NT_STATUS_IS_OK(status)) {
6226 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
6227 if (dir_hnd == NULL) {
6228 status = map_nt_error_from_unix(errno);
6232 status = NT_STATUS_NO_SUCH_FILE;
6234 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6235 * - gentest fix. JRA
6238 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname->st))) {
6239 files_struct *fsp = NULL;
6241 char *destname = NULL;
6242 bool sysdir_entry = False;
6244 /* Quick check for "." and ".." */
6245 if (ISDOT(dname) || ISDOTDOT(dname)) {
6247 sysdir_entry = True;
6253 if (!is_visible_file(conn, directory, dname, &smb_fname->st,
6258 if(!mask_match(dname, mask, conn->case_sensitive)) {
6263 status = NT_STATUS_OBJECT_NAME_INVALID;
6267 fname = talloc_asprintf(ctx,
6272 status = NT_STATUS_NO_MEMORY;
6276 if (!resolve_wildcards(ctx,
6277 fname,newname,&destname)) {
6278 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6284 status = NT_STATUS_NO_MEMORY;
6288 ZERO_STRUCT(smb_fname->st);
6289 if (posix_pathnames) {
6290 SMB_VFS_LSTAT(conn, fname, &smb_fname->st);
6292 SMB_VFS_STAT(conn, fname, &smb_fname->st);
6297 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6298 create_options |= FILE_DIRECTORY_FILE;
6301 status = SMB_VFS_CREATE_FILE(
6304 0, /* root_dir_fid */
6306 0, /* create_file_flags */
6307 access_mask, /* access_mask */
6308 (FILE_SHARE_READ | /* share_access */
6310 FILE_OPEN, /* create_disposition*/
6311 create_options, /* create_options */
6312 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6313 0, /* oplock_request */
6314 0, /* allocation_size */
6319 &smb_fname->st); /* psbuf */
6321 if (!NT_STATUS_IS_OK(status)) {
6322 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6323 "returned %s rename %s -> %s\n",
6324 nt_errstr(status), directory, newname));
6328 status = rename_internals_fsp(conn, fsp, destname, dname,
6329 attrs, replace_if_exists);
6331 close_file(req, fsp, NORMAL_CLOSE);
6333 if (!NT_STATUS_IS_OK(status)) {
6334 DEBUG(3, ("rename_internals_fsp returned %s for "
6335 "rename %s -> %s\n", nt_errstr(status),
6336 directory, newname));
6342 DEBUG(3,("rename_internals: doing rename on %s -> "
6343 "%s\n",fname,destname));
6346 TALLOC_FREE(destname);
6348 TALLOC_FREE(dir_hnd);
6350 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6351 status = map_nt_error_from_unix(errno);
6355 TALLOC_FREE(smb_fname);
6356 TALLOC_FREE(smb_fname_new);
6360 /****************************************************************************
6362 ****************************************************************************/
6364 void reply_mv(struct smb_request *req)
6366 connection_struct *conn = req->conn;
6368 char *newname = NULL;
6372 bool src_has_wcard = False;
6373 bool dest_has_wcard = False;
6374 TALLOC_CTX *ctx = talloc_tos();
6376 START_PROFILE(SMBmv);
6379 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6384 attrs = SVAL(req->vwv+0, 0);
6386 p = (const char *)req->buf + 1;
6387 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6388 &status, &src_has_wcard);
6389 if (!NT_STATUS_IS_OK(status)) {
6390 reply_nterror(req, status);
6395 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6396 &status, &dest_has_wcard);
6397 if (!NT_STATUS_IS_OK(status)) {
6398 reply_nterror(req, status);
6403 status = resolve_dfspath_wcard(ctx, conn,
6404 req->flags2 & FLAGS2_DFS_PATHNAMES,
6408 if (!NT_STATUS_IS_OK(status)) {
6409 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6410 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6411 ERRSRV, ERRbadpath);
6415 reply_nterror(req, status);
6420 status = resolve_dfspath_wcard(ctx, conn,
6421 req->flags2 & FLAGS2_DFS_PATHNAMES,
6425 if (!NT_STATUS_IS_OK(status)) {
6426 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6427 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6428 ERRSRV, ERRbadpath);
6432 reply_nterror(req, status);
6437 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6439 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6440 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6441 if (!NT_STATUS_IS_OK(status)) {
6442 if (open_was_deferred(req->mid)) {
6443 /* We have re-scheduled this call. */
6447 reply_nterror(req, status);
6452 reply_outbuf(req, 0, 0);
6458 /*******************************************************************
6459 Copy a file as part of a reply_copy.
6460 ******************************************************************/
6463 * TODO: check error codes on all callers
6466 NTSTATUS copy_file(TALLOC_CTX *ctx,
6467 connection_struct *conn,
6468 struct smb_filename *smb_fname_src,
6469 struct smb_filename *smb_fname_dst,
6472 bool target_is_directory)
6474 struct smb_filename *smb_fname_dst_tmp = NULL;
6475 char *fname_src = NULL;
6476 char *fname_dst = NULL;
6478 files_struct *fsp1,*fsp2;
6480 uint32 new_create_disposition;
6484 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6485 if (!NT_STATUS_IS_OK(status)) {
6490 * If the target is a directory, extract the last component from the
6491 * src filename and append it to the dst filename
6493 if (target_is_directory) {
6496 /* dest/target can't be a stream if it's a directory. */
6497 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6499 p = strrchr_m(smb_fname_src->base_name,'/');
6503 p = smb_fname_src->base_name;
6505 smb_fname_dst_tmp->base_name =
6506 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6508 if (!smb_fname_dst_tmp->base_name) {
6509 status = NT_STATUS_NO_MEMORY;
6514 status = vfs_file_exist(conn, smb_fname_src);
6515 if (!NT_STATUS_IS_OK(status)) {
6519 if (!target_is_directory && count) {
6520 new_create_disposition = FILE_OPEN;
6522 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6523 0, ofun, NULL, NULL,
6524 &new_create_disposition,
6526 status = NT_STATUS_INVALID_PARAMETER;
6531 status = get_full_smb_filename(talloc_tos(), smb_fname_src, &fname_src);
6532 if (!NT_STATUS_IS_OK(status)) {
6536 /* Open the src file for reading. */
6537 status = SMB_VFS_CREATE_FILE(
6540 0, /* root_dir_fid */
6541 fname_src, /* fname */
6542 0, /* create_file_flags */
6543 FILE_GENERIC_READ, /* access_mask */
6544 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6545 FILE_OPEN, /* create_disposition*/
6546 0, /* create_options */
6547 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6548 INTERNAL_OPEN_ONLY, /* oplock_request */
6549 0, /* allocation_size */
6554 &smb_fname_src->st); /* psbuf */
6556 if (!NT_STATUS_IS_OK(status)) {
6560 dosattrs = dos_mode(conn, fname_src, &smb_fname_src->st);
6562 status = get_full_smb_filename(talloc_tos(), smb_fname_dst_tmp, &fname_dst);
6563 if (!NT_STATUS_IS_OK(status)) {
6567 if (SMB_VFS_STAT(conn, fname_dst, &smb_fname_dst_tmp->st) == -1) {
6568 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6571 /* Open the dst file for writing. */
6572 status = SMB_VFS_CREATE_FILE(
6575 0, /* root_dir_fid */
6576 fname_dst, /* fname */
6577 0, /* create_file_flags */
6578 FILE_GENERIC_WRITE, /* access_mask */
6579 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6580 new_create_disposition, /* create_disposition*/
6581 0, /* create_options */
6582 dosattrs, /* file_attributes */
6583 INTERNAL_OPEN_ONLY, /* oplock_request */
6584 0, /* allocation_size */
6589 &smb_fname_dst_tmp->st); /* psbuf */
6591 if (!NT_STATUS_IS_OK(status)) {
6592 close_file(NULL, fsp1, ERROR_CLOSE);
6596 if ((ofun&3) == 1) {
6597 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6598 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6600 * Stop the copy from occurring.
6603 smb_fname_src->st.st_ex_size = 0;
6607 /* Do the actual copy. */
6608 if (smb_fname_src->st.st_ex_size) {
6609 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6612 close_file(NULL, fsp1, NORMAL_CLOSE);
6614 /* Ensure the modtime is set correctly on the destination file. */
6615 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6618 * As we are opening fsp1 read-only we only expect
6619 * an error on close on fsp2 if we are out of space.
6620 * Thus we don't look at the error return from the
6623 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6625 if (!NT_STATUS_IS_OK(status)) {
6629 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6630 status = NT_STATUS_DISK_FULL;
6634 status = NT_STATUS_OK;
6637 TALLOC_FREE(smb_fname_dst_tmp);
6638 TALLOC_FREE(fname_src);
6639 TALLOC_FREE(fname_dst);
6643 /****************************************************************************
6644 Reply to a file copy.
6645 ****************************************************************************/
6647 void reply_copy(struct smb_request *req)
6649 connection_struct *conn = req->conn;
6650 struct smb_filename *smb_fname_src = NULL;
6651 struct smb_filename *smb_fname_dst = NULL;
6652 char *fname_src = NULL;
6653 char *fname_dst = NULL;
6654 char *fname_src_mask = NULL;
6655 char *fname_src_dir = NULL;
6658 int error = ERRnoaccess;
6663 bool target_is_directory=False;
6664 bool source_has_wild = False;
6665 bool dest_has_wild = False;
6667 TALLOC_CTX *ctx = talloc_tos();
6669 START_PROFILE(SMBcopy);
6672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6676 tid2 = SVAL(req->vwv+0, 0);
6677 ofun = SVAL(req->vwv+1, 0);
6678 flags = SVAL(req->vwv+2, 0);
6680 p = (const char *)req->buf;
6681 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6682 &status, &source_has_wild);
6683 if (!NT_STATUS_IS_OK(status)) {
6684 reply_nterror(req, status);
6687 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6688 &status, &dest_has_wild);
6689 if (!NT_STATUS_IS_OK(status)) {
6690 reply_nterror(req, status);
6694 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6696 if (tid2 != conn->cnum) {
6697 /* can't currently handle inter share copies XXXX */
6698 DEBUG(3,("Rejecting inter-share copy\n"));
6699 reply_doserror(req, ERRSRV, ERRinvdevice);
6703 status = resolve_dfspath_wcard(ctx, conn,
6704 req->flags2 & FLAGS2_DFS_PATHNAMES,
6708 if (!NT_STATUS_IS_OK(status)) {
6709 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6710 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6711 ERRSRV, ERRbadpath);
6714 reply_nterror(req, status);
6718 status = resolve_dfspath_wcard(ctx, conn,
6719 req->flags2 & FLAGS2_DFS_PATHNAMES,
6723 if (!NT_STATUS_IS_OK(status)) {
6724 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6725 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6726 ERRSRV, ERRbadpath);
6729 reply_nterror(req, status);
6733 status = unix_convert(ctx, conn, fname_src, &smb_fname_src,
6734 source_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6735 if (!NT_STATUS_IS_OK(status)) {
6736 reply_nterror(req, status);
6740 status = unix_convert(ctx, conn, fname_dst, &smb_fname_dst,
6741 dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6742 if (!NT_STATUS_IS_OK(status)) {
6743 reply_nterror(req, status);
6747 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6749 if ((flags&1) && target_is_directory) {
6750 reply_doserror(req, ERRDOS, ERRbadfile);
6754 if ((flags&2) && !target_is_directory) {
6755 reply_doserror(req, ERRDOS, ERRbadpath);
6759 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6760 /* wants a tree copy! XXXX */
6761 DEBUG(3,("Rejecting tree copy\n"));
6762 reply_doserror(req, ERRSRV, ERRerror);
6766 /* Split up the directory from the filename/mask. */
6767 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6768 &fname_src_dir, &fname_src_mask);
6769 if (!NT_STATUS_IS_OK(status)) {
6770 reply_nterror(req, NT_STATUS_NO_MEMORY);
6775 * We should only check the mangled cache
6776 * here if unix_convert failed. This means
6777 * that the path in 'mask' doesn't exist
6778 * on the file system and so we need to look
6779 * for a possible mangle. This patch from
6780 * Tine Smukavec <valentin.smukavec@hermes.si>.
6782 if (!VALID_STAT(smb_fname_src->st) &&
6783 mangle_is_mangled(fname_src_mask, conn->params)) {
6784 char *new_mask = NULL;
6785 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6786 &new_mask, conn->params);
6788 /* Use demangled name if one was successfully found. */
6790 TALLOC_FREE(fname_src_mask);
6791 fname_src_mask = new_mask;
6795 if (!source_has_wild) {
6798 * Only one file needs to be copied. Append the mask back onto
6801 TALLOC_FREE(smb_fname_src->base_name);
6802 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6806 if (!smb_fname_src->base_name) {
6807 reply_nterror(req, NT_STATUS_NO_MEMORY);
6811 if (dest_has_wild) {
6812 char *fname_dst_mod = NULL;
6813 if (!resolve_wildcards(smb_fname_dst,
6814 smb_fname_src->base_name,
6815 smb_fname_dst->base_name,
6817 reply_nterror(req, NT_STATUS_NO_MEMORY);
6820 TALLOC_FREE(smb_fname_dst->base_name);
6821 smb_fname_dst->base_name = fname_dst_mod;
6824 status = check_name(conn, smb_fname_src->base_name);
6825 if (!NT_STATUS_IS_OK(status)) {
6826 reply_nterror(req, status);
6830 status = check_name(conn, smb_fname_dst->base_name);
6831 if (!NT_STATUS_IS_OK(status)) {
6832 reply_nterror(req, status);
6836 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6837 ofun, count, target_is_directory);
6839 if(!NT_STATUS_IS_OK(status)) {
6840 reply_nterror(req, status);
6846 struct smb_Dir *dir_hnd = NULL;
6847 const char *dname = NULL;
6851 * There is a wildcard that requires us to actually read the
6852 * src dir and copy each file matching the mask to the dst.
6853 * Right now streams won't be copied, but this could
6854 * presumably be added with a nested loop for reach dir entry.
6856 SMB_ASSERT(!smb_fname_src->stream_name);
6857 SMB_ASSERT(!smb_fname_dst->stream_name);
6859 smb_fname_src->stream_name = NULL;
6860 smb_fname_dst->stream_name = NULL;
6862 if (strequal(fname_src_mask,"????????.???")) {
6863 TALLOC_FREE(fname_src_mask);
6864 fname_src_mask = talloc_strdup(ctx, "*");
6865 if (!fname_src_mask) {
6866 reply_nterror(req, NT_STATUS_NO_MEMORY);
6871 status = check_name(conn, fname_src_dir);
6872 if (!NT_STATUS_IS_OK(status)) {
6873 reply_nterror(req, status);
6877 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6878 if (dir_hnd == NULL) {
6879 status = map_nt_error_from_unix(errno);
6880 reply_nterror(req, status);
6886 /* Iterate over the src dir copying each entry to the dst. */
6887 while ((dname = ReadDirName(dir_hnd, &offset,
6888 &smb_fname_src->st))) {
6889 char *destname = NULL;
6891 if (ISDOT(dname) || ISDOTDOT(dname)) {
6895 if (!is_visible_file(conn, fname_src_dir, dname,
6896 &smb_fname_src->st, false)) {
6900 if(!mask_match(dname, fname_src_mask,
6901 conn->case_sensitive)) {
6905 error = ERRnoaccess;
6907 /* Get the src smb_fname struct setup. */
6908 TALLOC_FREE(smb_fname_src->base_name);
6909 smb_fname_src->base_name =
6910 talloc_asprintf(smb_fname_src, "%s/%s",
6911 fname_src_dir, dname);
6913 if (!smb_fname_src->base_name) {
6914 TALLOC_FREE(dir_hnd);
6915 reply_nterror(req, NT_STATUS_NO_MEMORY);
6919 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6920 smb_fname_dst->base_name,
6925 TALLOC_FREE(dir_hnd);
6926 reply_nterror(req, NT_STATUS_NO_MEMORY);
6930 TALLOC_FREE(smb_fname_dst->base_name);
6931 smb_fname_dst->base_name = destname;
6933 status = check_name(conn, smb_fname_src->base_name);
6934 if (!NT_STATUS_IS_OK(status)) {
6935 TALLOC_FREE(dir_hnd);
6936 reply_nterror(req, status);
6940 status = check_name(conn, smb_fname_dst->base_name);
6941 if (!NT_STATUS_IS_OK(status)) {
6942 TALLOC_FREE(dir_hnd);
6943 reply_nterror(req, status);
6947 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
6948 smb_fname_src->base_name,
6949 smb_fname_dst->base_name));
6951 status = copy_file(ctx, conn, smb_fname_src,
6952 smb_fname_dst, ofun, count,
6953 target_is_directory);
6954 if (NT_STATUS_IS_OK(status)) {
6958 TALLOC_FREE(dir_hnd);
6963 /* Error on close... */
6965 reply_unixerror(req, ERRHRD, ERRgeneral);
6969 reply_doserror(req, ERRDOS, error);
6973 reply_outbuf(req, 1, 0);
6974 SSVAL(req->outbuf,smb_vwv0,count);
6976 TALLOC_FREE(smb_fname_src);
6977 TALLOC_FREE(smb_fname_dst);
6978 TALLOC_FREE(fname_src);
6979 TALLOC_FREE(fname_dst);
6980 TALLOC_FREE(fname_src_mask);
6981 TALLOC_FREE(fname_src_dir);
6983 END_PROFILE(SMBcopy);
6988 #define DBGC_CLASS DBGC_LOCKING
6990 /****************************************************************************
6991 Get a lock pid, dealing with large count requests.
6992 ****************************************************************************/
6994 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6995 bool large_file_format)
6997 if(!large_file_format)
6998 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
7000 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7003 /****************************************************************************
7004 Get a lock count, dealing with large count requests.
7005 ****************************************************************************/
7007 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7008 bool large_file_format)
7012 if(!large_file_format) {
7013 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7016 #if defined(HAVE_LONGLONG)
7017 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7018 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7019 #else /* HAVE_LONGLONG */
7022 * NT4.x seems to be broken in that it sends large file (64 bit)
7023 * lockingX calls even if the CAP_LARGE_FILES was *not*
7024 * negotiated. For boxes without large unsigned ints truncate the
7025 * lock count by dropping the top 32 bits.
7028 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7029 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7030 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7031 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7032 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7035 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7036 #endif /* HAVE_LONGLONG */
7042 #if !defined(HAVE_LONGLONG)
7043 /****************************************************************************
7044 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7045 ****************************************************************************/
7047 static uint32 map_lock_offset(uint32 high, uint32 low)
7051 uint32 highcopy = high;
7054 * Try and find out how many significant bits there are in high.
7057 for(i = 0; highcopy; i++)
7061 * We use 31 bits not 32 here as POSIX
7062 * lock offsets may not be negative.
7065 mask = (~0) << (31 - i);
7068 return 0; /* Fail. */
7074 #endif /* !defined(HAVE_LONGLONG) */
7076 /****************************************************************************
7077 Get a lock offset, dealing with large offset requests.
7078 ****************************************************************************/
7080 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7081 bool large_file_format, bool *err)
7083 uint64_t offset = 0;
7087 if(!large_file_format) {
7088 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7091 #if defined(HAVE_LONGLONG)
7092 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7093 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7094 #else /* HAVE_LONGLONG */
7097 * NT4.x seems to be broken in that it sends large file (64 bit)
7098 * lockingX calls even if the CAP_LARGE_FILES was *not*
7099 * negotiated. For boxes without large unsigned ints mangle the
7100 * lock offset by mapping the top 32 bits onto the lower 32.
7103 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7104 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7105 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7108 if((new_low = map_lock_offset(high, low)) == 0) {
7110 return (uint64_t)-1;
7113 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7114 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7115 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7116 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7119 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7120 #endif /* HAVE_LONGLONG */
7126 /****************************************************************************
7127 Reply to a lockingX request.
7128 ****************************************************************************/
7130 void reply_lockingX(struct smb_request *req)
7132 connection_struct *conn = req->conn;
7134 unsigned char locktype;
7135 unsigned char oplocklevel;
7138 uint64_t count = 0, offset = 0;
7142 const uint8_t *data;
7143 bool large_file_format;
7145 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7147 START_PROFILE(SMBlockingX);
7150 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7151 END_PROFILE(SMBlockingX);
7155 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7156 locktype = CVAL(req->vwv+3, 0);
7157 oplocklevel = CVAL(req->vwv+3, 1);
7158 num_ulocks = SVAL(req->vwv+6, 0);
7159 num_locks = SVAL(req->vwv+7, 0);
7160 lock_timeout = IVAL(req->vwv+4, 0);
7161 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7163 if (!check_fsp(conn, req, fsp)) {
7164 END_PROFILE(SMBlockingX);
7170 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7171 /* we don't support these - and CANCEL_LOCK makes w2k
7172 and XP reboot so I don't really want to be
7173 compatible! (tridge) */
7174 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7175 END_PROFILE(SMBlockingX);
7179 /* Check if this is an oplock break on a file
7180 we have granted an oplock on.
7182 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7183 /* Client can insist on breaking to none. */
7184 bool break_to_none = (oplocklevel == 0);
7187 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7188 "for fnum = %d\n", (unsigned int)oplocklevel,
7192 * Make sure we have granted an exclusive or batch oplock on
7196 if (fsp->oplock_type == 0) {
7198 /* The Samba4 nbench simulator doesn't understand
7199 the difference between break to level2 and break
7200 to none from level2 - it sends oplock break
7201 replies in both cases. Don't keep logging an error
7202 message here - just ignore it. JRA. */
7204 DEBUG(5,("reply_lockingX: Error : oplock break from "
7205 "client for fnum = %d (oplock=%d) and no "
7206 "oplock granted on this file (%s).\n",
7207 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
7209 /* if this is a pure oplock break request then don't
7211 if (num_locks == 0 && num_ulocks == 0) {
7212 END_PROFILE(SMBlockingX);
7215 END_PROFILE(SMBlockingX);
7216 reply_doserror(req, ERRDOS, ERRlock);
7221 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7223 result = remove_oplock(fsp);
7225 result = downgrade_oplock(fsp);
7229 DEBUG(0, ("reply_lockingX: error in removing "
7230 "oplock on file %s\n", fsp->fsp_name));
7231 /* Hmmm. Is this panic justified? */
7232 smb_panic("internal tdb error");
7235 reply_to_oplock_break_requests(fsp);
7237 /* if this is a pure oplock break request then don't send a
7239 if (num_locks == 0 && num_ulocks == 0) {
7240 /* Sanity check - ensure a pure oplock break is not a
7242 if(CVAL(req->vwv+0, 0) != 0xff)
7243 DEBUG(0,("reply_lockingX: Error : pure oplock "
7244 "break is a chained %d request !\n",
7245 (unsigned int)CVAL(req->vwv+0, 0)));
7246 END_PROFILE(SMBlockingX);
7252 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7253 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7254 END_PROFILE(SMBlockingX);
7258 /* Data now points at the beginning of the list
7259 of smb_unlkrng structs */
7260 for(i = 0; i < (int)num_ulocks; i++) {
7261 lock_pid = get_lock_pid( data, i, large_file_format);
7262 count = get_lock_count( data, i, large_file_format);
7263 offset = get_lock_offset( data, i, large_file_format, &err);
7266 * There is no error code marked "stupid client bug".... :-).
7269 END_PROFILE(SMBlockingX);
7270 reply_doserror(req, ERRDOS, ERRnoaccess);
7274 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
7275 "pid %u, file %s\n", (double)offset, (double)count,
7276 (unsigned int)lock_pid, fsp->fsp_name ));
7278 status = do_unlock(smbd_messaging_context(),
7285 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
7286 nt_errstr(status)));
7288 if (NT_STATUS_V(status)) {
7289 END_PROFILE(SMBlockingX);
7290 reply_nterror(req, status);
7295 /* Setup the timeout in seconds. */
7297 if (!lp_blocking_locks(SNUM(conn))) {
7301 /* Now do any requested locks */
7302 data += ((large_file_format ? 20 : 10)*num_ulocks);
7304 /* Data now points at the beginning of the list
7305 of smb_lkrng structs */
7307 for(i = 0; i < (int)num_locks; i++) {
7308 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
7309 READ_LOCK:WRITE_LOCK);
7310 lock_pid = get_lock_pid( data, i, large_file_format);
7311 count = get_lock_count( data, i, large_file_format);
7312 offset = get_lock_offset( data, i, large_file_format, &err);
7315 * There is no error code marked "stupid client bug".... :-).
7318 END_PROFILE(SMBlockingX);
7319 reply_doserror(req, ERRDOS, ERRnoaccess);
7323 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
7324 "%u, file %s timeout = %d\n", (double)offset,
7325 (double)count, (unsigned int)lock_pid,
7326 fsp->fsp_name, (int)lock_timeout ));
7328 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7329 struct blocking_lock_record *blr = NULL;
7331 if (lp_blocking_locks(SNUM(conn))) {
7333 /* Schedule a message to ourselves to
7334 remove the blocking lock record and
7335 return the right error. */
7337 blr = blocking_lock_cancel(fsp,
7343 NT_STATUS_FILE_LOCK_CONFLICT);
7345 END_PROFILE(SMBlockingX);
7350 ERRcancelviolation));
7354 /* Remove a matching pending lock. */
7355 status = do_lock_cancel(fsp,
7362 bool blocking_lock = lock_timeout ? True : False;
7363 bool defer_lock = False;
7364 struct byte_range_lock *br_lck;
7365 uint32 block_smbpid;
7367 br_lck = do_lock(smbd_messaging_context(),
7379 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7380 /* Windows internal resolution for blocking locks seems
7381 to be about 200ms... Don't wait for less than that. JRA. */
7382 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7383 lock_timeout = lp_lock_spin_time();
7388 /* This heuristic seems to match W2K3 very well. If a
7389 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7390 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7391 far as I can tell. Replacement for do_lock_spin(). JRA. */
7393 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7394 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7396 lock_timeout = lp_lock_spin_time();
7399 if (br_lck && defer_lock) {
7401 * A blocking lock was requested. Package up
7402 * this smb into a queued request and push it
7403 * onto the blocking lock queue.
7405 if(push_blocking_lock_request(br_lck,
7416 TALLOC_FREE(br_lck);
7417 END_PROFILE(SMBlockingX);
7422 TALLOC_FREE(br_lck);
7425 if (NT_STATUS_V(status)) {
7426 END_PROFILE(SMBlockingX);
7427 reply_nterror(req, status);
7432 /* If any of the above locks failed, then we must unlock
7433 all of the previous locks (X/Open spec). */
7435 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7439 * Ensure we don't do a remove on the lock that just failed,
7440 * as under POSIX rules, if we have a lock already there, we
7441 * will delete it (and we shouldn't) .....
7443 for(i--; i >= 0; i--) {
7444 lock_pid = get_lock_pid( data, i, large_file_format);
7445 count = get_lock_count( data, i, large_file_format);
7446 offset = get_lock_offset( data, i, large_file_format,
7450 * There is no error code marked "stupid client
7454 END_PROFILE(SMBlockingX);
7455 reply_doserror(req, ERRDOS, ERRnoaccess);
7459 do_unlock(smbd_messaging_context(),
7466 END_PROFILE(SMBlockingX);
7467 reply_nterror(req, status);
7471 reply_outbuf(req, 2, 0);
7473 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7474 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7476 END_PROFILE(SMBlockingX);
7481 #define DBGC_CLASS DBGC_ALL
7483 /****************************************************************************
7484 Reply to a SMBreadbmpx (read block multiplex) request.
7485 Always reply with an error, if someone has a platform really needs this,
7486 please contact vl@samba.org
7487 ****************************************************************************/
7489 void reply_readbmpx(struct smb_request *req)
7491 START_PROFILE(SMBreadBmpx);
7492 reply_doserror(req, ERRSRV, ERRuseSTD);
7493 END_PROFILE(SMBreadBmpx);
7497 /****************************************************************************
7498 Reply to a SMBreadbs (read block multiplex secondary) request.
7499 Always reply with an error, if someone has a platform really needs this,
7500 please contact vl@samba.org
7501 ****************************************************************************/
7503 void reply_readbs(struct smb_request *req)
7505 START_PROFILE(SMBreadBs);
7506 reply_doserror(req, ERRSRV, ERRuseSTD);
7507 END_PROFILE(SMBreadBs);
7511 /****************************************************************************
7512 Reply to a SMBsetattrE.
7513 ****************************************************************************/
7515 void reply_setattrE(struct smb_request *req)
7517 connection_struct *conn = req->conn;
7518 struct smb_file_time ft;
7520 SMB_STRUCT_STAT sbuf;
7523 START_PROFILE(SMBsetattrE);
7527 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7528 END_PROFILE(SMBsetattrE);
7532 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7534 if(!fsp || (fsp->conn != conn)) {
7535 reply_doserror(req, ERRDOS, ERRbadfid);
7536 END_PROFILE(SMBsetattrE);
7542 * Convert the DOS times into unix times.
7545 ft.atime = convert_time_t_to_timespec(
7546 srv_make_unix_date2(req->vwv+3));
7547 ft.mtime = convert_time_t_to_timespec(
7548 srv_make_unix_date2(req->vwv+5));
7549 ft.create_time = convert_time_t_to_timespec(
7550 srv_make_unix_date2(req->vwv+1));
7552 reply_outbuf(req, 0, 0);
7555 * Patch from Ray Frush <frush@engr.colostate.edu>
7556 * Sometimes times are sent as zero - ignore them.
7559 /* Ensure we have a valid stat struct for the source. */
7560 if (fsp->fh->fd != -1) {
7561 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7562 status = map_nt_error_from_unix(errno);
7563 reply_nterror(req, status);
7564 END_PROFILE(SMBsetattrE);
7570 if (fsp->posix_open) {
7571 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
7573 ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
7576 status = map_nt_error_from_unix(errno);
7577 reply_nterror(req, status);
7578 END_PROFILE(SMBsetattrE);
7583 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7585 if (!NT_STATUS_IS_OK(status)) {
7586 reply_doserror(req, ERRDOS, ERRnoaccess);
7587 END_PROFILE(SMBsetattrE);
7591 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7594 (unsigned int)ft.atime.tv_sec,
7595 (unsigned int)ft.mtime.tv_sec,
7596 (unsigned int)ft.create_time.tv_sec
7599 END_PROFILE(SMBsetattrE);
7604 /* Back from the dead for OS/2..... JRA. */
7606 /****************************************************************************
7607 Reply to a SMBwritebmpx (write block multiplex primary) request.
7608 Always reply with an error, if someone has a platform really needs this,
7609 please contact vl@samba.org
7610 ****************************************************************************/
7612 void reply_writebmpx(struct smb_request *req)
7614 START_PROFILE(SMBwriteBmpx);
7615 reply_doserror(req, ERRSRV, ERRuseSTD);
7616 END_PROFILE(SMBwriteBmpx);
7620 /****************************************************************************
7621 Reply to a SMBwritebs (write block multiplex secondary) request.
7622 Always reply with an error, if someone has a platform really needs this,
7623 please contact vl@samba.org
7624 ****************************************************************************/
7626 void reply_writebs(struct smb_request *req)
7628 START_PROFILE(SMBwriteBs);
7629 reply_doserror(req, ERRSRV, ERRuseSTD);
7630 END_PROFILE(SMBwriteBs);
7634 /****************************************************************************
7635 Reply to a SMBgetattrE.
7636 ****************************************************************************/
7638 void reply_getattrE(struct smb_request *req)
7640 connection_struct *conn = req->conn;
7641 SMB_STRUCT_STAT sbuf;
7644 struct timespec create_ts;
7646 START_PROFILE(SMBgetattrE);
7649 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7650 END_PROFILE(SMBgetattrE);
7654 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7656 if(!fsp || (fsp->conn != conn)) {
7657 reply_doserror(req, ERRDOS, ERRbadfid);
7658 END_PROFILE(SMBgetattrE);
7662 /* Do an fstat on this file */
7663 if(fsp_stat(fsp, &sbuf)) {
7664 reply_unixerror(req, ERRDOS, ERRnoaccess);
7665 END_PROFILE(SMBgetattrE);
7669 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7672 * Convert the times into dos times. Set create
7673 * date to be last modify date as UNIX doesn't save
7677 reply_outbuf(req, 11, 0);
7679 create_ts = sbuf.st_ex_btime;
7680 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7681 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7682 convert_timespec_to_time_t(sbuf.st_ex_atime));
7683 /* Should we check pending modtime here ? JRA */
7684 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7685 convert_timespec_to_time_t(sbuf.st_ex_mtime));
7688 SIVAL(req->outbuf, smb_vwv6, 0);
7689 SIVAL(req->outbuf, smb_vwv8, 0);
7691 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7692 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_ex_size);
7693 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7695 SSVAL(req->outbuf,smb_vwv10, mode);
7697 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7699 END_PROFILE(SMBgetattrE);