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);
859 req->tid = conn->cnum;
864 /****************************************************************************
865 Reply to an unknown type.
866 ****************************************************************************/
868 void reply_unknown_new(struct smb_request *req, uint8 type)
870 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
871 smb_fn_name(type), type, type));
872 reply_doserror(req, ERRSRV, ERRunknownsmb);
876 /****************************************************************************
878 conn POINTER CAN BE NULL HERE !
879 ****************************************************************************/
881 void reply_ioctl(struct smb_request *req)
883 connection_struct *conn = req->conn;
890 START_PROFILE(SMBioctl);
893 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
894 END_PROFILE(SMBioctl);
898 device = SVAL(req->vwv+1, 0);
899 function = SVAL(req->vwv+2, 0);
900 ioctl_code = (device << 16) + function;
902 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
904 switch (ioctl_code) {
905 case IOCTL_QUERY_JOB_INFO:
909 reply_doserror(req, ERRSRV, ERRnosupport);
910 END_PROFILE(SMBioctl);
914 reply_outbuf(req, 8, replysize+1);
915 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
916 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
917 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
918 p = smb_buf(req->outbuf);
919 memset(p, '\0', replysize+1); /* valgrind-safe. */
920 p += 1; /* Allow for alignment */
922 switch (ioctl_code) {
923 case IOCTL_QUERY_JOB_INFO:
925 files_struct *fsp = file_fsp(
926 req, SVAL(req->vwv+0, 0));
928 reply_doserror(req, ERRDOS, ERRbadfid);
929 END_PROFILE(SMBioctl);
932 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
933 srvstr_push((char *)req->outbuf, req->flags2, p+2,
935 STR_TERMINATE|STR_ASCII);
937 srvstr_push((char *)req->outbuf, req->flags2,
938 p+18, lp_servicename(SNUM(conn)),
939 13, STR_TERMINATE|STR_ASCII);
947 END_PROFILE(SMBioctl);
951 /****************************************************************************
952 Strange checkpath NTSTATUS mapping.
953 ****************************************************************************/
955 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
957 /* Strange DOS error code semantics only for checkpath... */
958 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
959 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
960 /* We need to map to ERRbadpath */
961 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
967 /****************************************************************************
968 Reply to a checkpath.
969 ****************************************************************************/
971 void reply_checkpath(struct smb_request *req)
973 connection_struct *conn = req->conn;
974 struct smb_filename *smb_fname = NULL;
977 TALLOC_CTX *ctx = talloc_tos();
979 START_PROFILE(SMBcheckpath);
981 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
982 STR_TERMINATE, &status);
984 if (!NT_STATUS_IS_OK(status)) {
985 status = map_checkpath_error(req->flags2, status);
986 reply_nterror(req, status);
987 END_PROFILE(SMBcheckpath);
991 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
993 status = filename_convert(ctx,
995 req->flags2 & FLAGS2_DFS_PATHNAMES,
1000 if (!NT_STATUS_IS_OK(status)) {
1001 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1002 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1003 ERRSRV, ERRbadpath);
1004 END_PROFILE(SMBcheckpath);
1010 if (!VALID_STAT(smb_fname->st) &&
1011 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1012 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1013 smb_fname_str_dbg(smb_fname), strerror(errno)));
1014 status = map_nt_error_from_unix(errno);
1018 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1019 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1020 ERRDOS, ERRbadpath);
1024 reply_outbuf(req, 0, 0);
1027 /* We special case this - as when a Windows machine
1028 is parsing a path is steps through the components
1029 one at a time - if a component fails it expects
1030 ERRbadpath, not ERRbadfile.
1032 status = map_checkpath_error(req->flags2, status);
1033 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1035 * Windows returns different error codes if
1036 * the parent directory is valid but not the
1037 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1038 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1039 * if the path is invalid.
1041 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1042 ERRDOS, ERRbadpath);
1046 reply_nterror(req, status);
1049 TALLOC_FREE(smb_fname);
1050 END_PROFILE(SMBcheckpath);
1054 /****************************************************************************
1056 ****************************************************************************/
1058 void reply_getatr(struct smb_request *req)
1060 connection_struct *conn = req->conn;
1061 struct smb_filename *smb_fname = NULL;
1068 TALLOC_CTX *ctx = talloc_tos();
1069 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1071 START_PROFILE(SMBgetatr);
1073 p = (const char *)req->buf + 1;
1074 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1075 if (!NT_STATUS_IS_OK(status)) {
1076 reply_nterror(req, status);
1080 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1081 under WfWg - weird! */
1082 if (*fname == '\0') {
1083 mode = aHIDDEN | aDIR;
1084 if (!CAN_WRITE(conn)) {
1090 status = filename_convert(ctx,
1092 req->flags2 & FLAGS2_DFS_PATHNAMES,
1096 if (!NT_STATUS_IS_OK(status)) {
1097 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1098 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1099 ERRSRV, ERRbadpath);
1102 reply_nterror(req, status);
1105 if (!VALID_STAT(smb_fname->st) &&
1106 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1107 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1108 smb_fname_str_dbg(smb_fname),
1110 reply_nterror(req, map_nt_error_from_unix(errno));
1114 mode = dos_mode(conn, smb_fname);
1115 size = smb_fname->st.st_ex_size;
1117 if (ask_sharemode) {
1118 struct timespec write_time_ts;
1119 struct file_id fileid;
1121 ZERO_STRUCT(write_time_ts);
1122 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1123 get_file_infos(fileid, NULL, &write_time_ts);
1124 if (!null_timespec(write_time_ts)) {
1125 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1129 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1135 reply_outbuf(req, 10, 0);
1137 SSVAL(req->outbuf,smb_vwv0,mode);
1138 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1139 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1141 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1143 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1145 if (Protocol >= PROTOCOL_NT1) {
1146 SSVAL(req->outbuf, smb_flg2,
1147 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1150 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1151 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1154 TALLOC_FREE(smb_fname);
1156 END_PROFILE(SMBgetatr);
1160 /****************************************************************************
1162 ****************************************************************************/
1164 void reply_setatr(struct smb_request *req)
1166 struct smb_file_time ft;
1167 connection_struct *conn = req->conn;
1168 struct smb_filename *smb_fname = NULL;
1174 TALLOC_CTX *ctx = talloc_tos();
1176 START_PROFILE(SMBsetatr);
1181 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1185 p = (const char *)req->buf + 1;
1186 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1187 if (!NT_STATUS_IS_OK(status)) {
1188 reply_nterror(req, status);
1192 status = filename_convert(ctx,
1194 req->flags2 & FLAGS2_DFS_PATHNAMES,
1198 if (!NT_STATUS_IS_OK(status)) {
1199 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1200 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1201 ERRSRV, ERRbadpath);
1204 reply_nterror(req, status);
1208 if (smb_fname->base_name[0] == '.' &&
1209 smb_fname->base_name[1] == '\0') {
1211 * Not sure here is the right place to catch this
1212 * condition. Might be moved to somewhere else later -- vl
1214 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1218 mode = SVAL(req->vwv+0, 0);
1219 mtime = srv_make_unix_date3(req->vwv+1);
1221 ft.mtime = convert_time_t_to_timespec(mtime);
1222 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1223 if (!NT_STATUS_IS_OK(status)) {
1224 reply_nterror(req, status);
1228 if (mode != FILE_ATTRIBUTE_NORMAL) {
1229 if (VALID_STAT_OF_DIR(smb_fname->st))
1234 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1236 reply_nterror(req, map_nt_error_from_unix(errno));
1241 reply_outbuf(req, 0, 0);
1243 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1246 TALLOC_FREE(smb_fname);
1247 END_PROFILE(SMBsetatr);
1251 /****************************************************************************
1253 ****************************************************************************/
1255 void reply_dskattr(struct smb_request *req)
1257 connection_struct *conn = req->conn;
1258 uint64_t dfree,dsize,bsize;
1259 START_PROFILE(SMBdskattr);
1261 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1262 reply_nterror(req, map_nt_error_from_unix(errno));
1263 END_PROFILE(SMBdskattr);
1267 reply_outbuf(req, 5, 0);
1269 if (Protocol <= PROTOCOL_LANMAN2) {
1270 double total_space, free_space;
1271 /* we need to scale this to a number that DOS6 can handle. We
1272 use floating point so we can handle large drives on systems
1273 that don't have 64 bit integers
1275 we end up displaying a maximum of 2G to DOS systems
1277 total_space = dsize * (double)bsize;
1278 free_space = dfree * (double)bsize;
1280 dsize = (uint64_t)((total_space+63*512) / (64*512));
1281 dfree = (uint64_t)((free_space+63*512) / (64*512));
1283 if (dsize > 0xFFFF) dsize = 0xFFFF;
1284 if (dfree > 0xFFFF) dfree = 0xFFFF;
1286 SSVAL(req->outbuf,smb_vwv0,dsize);
1287 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1288 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1289 SSVAL(req->outbuf,smb_vwv3,dfree);
1291 SSVAL(req->outbuf,smb_vwv0,dsize);
1292 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1293 SSVAL(req->outbuf,smb_vwv2,512);
1294 SSVAL(req->outbuf,smb_vwv3,dfree);
1297 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1299 END_PROFILE(SMBdskattr);
1304 * Utility function to split the filename from the directory.
1306 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1307 char **fname_dir_out,
1308 char **fname_mask_out)
1310 const char *p = NULL;
1311 char *fname_dir = NULL;
1312 char *fname_mask = NULL;
1314 p = strrchr_m(fname_in, '/');
1316 fname_dir = talloc_strdup(ctx, ".");
1317 fname_mask = talloc_strdup(ctx, fname_in);
1319 fname_dir = talloc_strndup(ctx, fname_in,
1320 PTR_DIFF(p, fname_in));
1321 fname_mask = talloc_strdup(ctx, p+1);
1324 if (!fname_dir || !fname_mask) {
1325 TALLOC_FREE(fname_dir);
1326 TALLOC_FREE(fname_mask);
1327 return NT_STATUS_NO_MEMORY;
1330 *fname_dir_out = fname_dir;
1331 *fname_mask_out = fname_mask;
1332 return NT_STATUS_OK;
1335 /****************************************************************************
1337 Can be called from SMBsearch, SMBffirst or SMBfunique.
1338 ****************************************************************************/
1340 void reply_search(struct smb_request *req)
1342 connection_struct *conn = req->conn;
1344 const char *mask = NULL;
1345 char *directory = NULL;
1349 struct timespec date;
1351 unsigned int numentries = 0;
1352 unsigned int maxentries = 0;
1353 bool finished = False;
1358 bool check_descend = False;
1359 bool expect_close = False;
1361 bool mask_contains_wcard = False;
1362 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1363 TALLOC_CTX *ctx = talloc_tos();
1364 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1366 START_PROFILE(SMBsearch);
1369 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1370 END_PROFILE(SMBsearch);
1374 if (lp_posix_pathnames()) {
1375 reply_unknown_new(req, req->cmd);
1376 END_PROFILE(SMBsearch);
1380 /* If we were called as SMBffirst then we must expect close. */
1381 if(req->cmd == SMBffirst) {
1382 expect_close = True;
1385 reply_outbuf(req, 1, 3);
1386 maxentries = SVAL(req->vwv+0, 0);
1387 dirtype = SVAL(req->vwv+1, 0);
1388 p = (const char *)req->buf + 1;
1389 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1390 &nt_status, &mask_contains_wcard);
1391 if (!NT_STATUS_IS_OK(nt_status)) {
1392 reply_nterror(req, nt_status);
1393 END_PROFILE(SMBsearch);
1398 status_len = SVAL(p, 0);
1401 /* dirtype &= ~aDIR; */
1403 if (status_len == 0) {
1404 struct smb_filename *smb_fname = NULL;
1406 nt_status = resolve_dfspath_wcard(ctx, conn,
1407 req->flags2 & FLAGS2_DFS_PATHNAMES,
1410 &mask_contains_wcard);
1411 if (!NT_STATUS_IS_OK(nt_status)) {
1412 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1413 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1414 ERRSRV, ERRbadpath);
1415 END_PROFILE(SMBsearch);
1418 reply_nterror(req, nt_status);
1419 END_PROFILE(SMBsearch);
1423 nt_status = unix_convert(ctx, conn, path, &smb_fname,
1424 UCF_ALLOW_WCARD_LCOMP);
1425 if (!NT_STATUS_IS_OK(nt_status)) {
1426 reply_nterror(req, nt_status);
1427 END_PROFILE(SMBsearch);
1431 nt_status = get_full_smb_filename(ctx, smb_fname, &directory);
1432 TALLOC_FREE(smb_fname);
1433 if (!NT_STATUS_IS_OK(nt_status)) {
1434 reply_nterror(req, nt_status);
1435 END_PROFILE(SMBsearch);
1439 nt_status = check_name(conn, directory);
1440 if (!NT_STATUS_IS_OK(nt_status)) {
1441 reply_nterror(req, nt_status);
1442 END_PROFILE(SMBsearch);
1446 p = strrchr_m(directory,'/');
1447 if ((p != NULL) && (*directory != '/')) {
1449 directory = talloc_strndup(ctx, directory,
1450 PTR_DIFF(p, directory));
1453 directory = talloc_strdup(ctx,".");
1457 reply_nterror(req, NT_STATUS_NO_MEMORY);
1458 END_PROFILE(SMBsearch);
1462 memset((char *)status,'\0',21);
1463 SCVAL(status,0,(dirtype & 0x1F));
1465 nt_status = dptr_create(conn,
1471 mask_contains_wcard,
1474 if (!NT_STATUS_IS_OK(nt_status)) {
1475 reply_nterror(req, nt_status);
1476 END_PROFILE(SMBsearch);
1479 dptr_num = dptr_dnum(conn->dirptr);
1483 memcpy(status,p,21);
1484 status_dirtype = CVAL(status,0) & 0x1F;
1485 if (status_dirtype != (dirtype & 0x1F)) {
1486 dirtype = status_dirtype;
1489 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1490 if (!conn->dirptr) {
1493 string_set(&conn->dirpath,dptr_path(dptr_num));
1494 mask = dptr_wcard(dptr_num);
1499 * For a 'continue' search we have no string. So
1500 * check from the initial saved string.
1502 mask_contains_wcard = ms_has_wild(mask);
1503 dirtype = dptr_attr(dptr_num);
1506 DEBUG(4,("dptr_num is %d\n",dptr_num));
1508 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1509 dptr_init_search_op(conn->dirptr);
1511 if ((dirtype&0x1F) == aVOLID) {
1512 char buf[DIR_STRUCT_SIZE];
1513 memcpy(buf,status,21);
1514 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1515 0,aVOLID,0,!allow_long_path_components)) {
1516 reply_nterror(req, NT_STATUS_NO_MEMORY);
1517 END_PROFILE(SMBsearch);
1520 dptr_fill(buf+12,dptr_num);
1521 if (dptr_zero(buf+12) && (status_len==0)) {
1526 if (message_push_blob(&req->outbuf,
1527 data_blob_const(buf, sizeof(buf)))
1529 reply_nterror(req, NT_STATUS_NO_MEMORY);
1530 END_PROFILE(SMBsearch);
1538 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1541 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1542 conn->dirpath,lp_dontdescend(SNUM(conn))));
1543 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1544 check_descend = True;
1547 for (i=numentries;(i<maxentries) && !finished;i++) {
1548 finished = !get_dir_entry(ctx,
1559 char buf[DIR_STRUCT_SIZE];
1560 memcpy(buf,status,21);
1561 if (!make_dir_struct(ctx,
1567 convert_timespec_to_time_t(date),
1568 !allow_long_path_components)) {
1569 reply_nterror(req, NT_STATUS_NO_MEMORY);
1570 END_PROFILE(SMBsearch);
1573 if (!dptr_fill(buf+12,dptr_num)) {
1576 if (message_push_blob(&req->outbuf,
1577 data_blob_const(buf, sizeof(buf)))
1579 reply_nterror(req, NT_STATUS_NO_MEMORY);
1580 END_PROFILE(SMBsearch);
1590 /* If we were called as SMBffirst with smb_search_id == NULL
1591 and no entries were found then return error and close dirptr
1594 if (numentries == 0) {
1595 dptr_close(&dptr_num);
1596 } else if(expect_close && status_len == 0) {
1597 /* Close the dptr - we know it's gone */
1598 dptr_close(&dptr_num);
1601 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1602 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1603 dptr_close(&dptr_num);
1606 if ((numentries == 0) && !mask_contains_wcard) {
1607 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1608 END_PROFILE(SMBsearch);
1612 SSVAL(req->outbuf,smb_vwv0,numentries);
1613 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1614 SCVAL(smb_buf(req->outbuf),0,5);
1615 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1617 /* The replies here are never long name. */
1618 SSVAL(req->outbuf, smb_flg2,
1619 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1620 if (!allow_long_path_components) {
1621 SSVAL(req->outbuf, smb_flg2,
1622 SVAL(req->outbuf, smb_flg2)
1623 & (~FLAGS2_LONG_PATH_COMPONENTS));
1626 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1627 SSVAL(req->outbuf, smb_flg2,
1628 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1631 directory = dptr_path(dptr_num);
1634 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1635 smb_fn_name(req->cmd),
1637 directory ? directory : "./",
1642 END_PROFILE(SMBsearch);
1646 /****************************************************************************
1647 Reply to a fclose (stop directory search).
1648 ****************************************************************************/
1650 void reply_fclose(struct smb_request *req)
1658 bool path_contains_wcard = False;
1659 TALLOC_CTX *ctx = talloc_tos();
1661 START_PROFILE(SMBfclose);
1663 if (lp_posix_pathnames()) {
1664 reply_unknown_new(req, req->cmd);
1665 END_PROFILE(SMBfclose);
1669 p = (const char *)req->buf + 1;
1670 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1671 &err, &path_contains_wcard);
1672 if (!NT_STATUS_IS_OK(err)) {
1673 reply_nterror(req, err);
1674 END_PROFILE(SMBfclose);
1678 status_len = SVAL(p,0);
1681 if (status_len == 0) {
1682 reply_doserror(req, ERRSRV, ERRsrverror);
1683 END_PROFILE(SMBfclose);
1687 memcpy(status,p,21);
1689 if(dptr_fetch(status+12,&dptr_num)) {
1690 /* Close the dptr - we know it's gone */
1691 dptr_close(&dptr_num);
1694 reply_outbuf(req, 1, 0);
1695 SSVAL(req->outbuf,smb_vwv0,0);
1697 DEBUG(3,("search close\n"));
1699 END_PROFILE(SMBfclose);
1703 /****************************************************************************
1705 ****************************************************************************/
1707 void reply_open(struct smb_request *req)
1709 connection_struct *conn = req->conn;
1710 struct smb_filename *smb_fname = NULL;
1722 uint32 create_disposition;
1723 uint32 create_options = 0;
1725 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1726 TALLOC_CTX *ctx = talloc_tos();
1728 START_PROFILE(SMBopen);
1731 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1735 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1736 deny_mode = SVAL(req->vwv+0, 0);
1737 dos_attr = SVAL(req->vwv+1, 0);
1739 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1740 STR_TERMINATE, &status);
1741 if (!NT_STATUS_IS_OK(status)) {
1742 reply_nterror(req, status);
1746 status = filename_convert(ctx,
1748 req->flags2 & FLAGS2_DFS_PATHNAMES,
1752 if (!NT_STATUS_IS_OK(status)) {
1753 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1754 reply_botherror(req,
1755 NT_STATUS_PATH_NOT_COVERED,
1756 ERRSRV, ERRbadpath);
1759 reply_nterror(req, status);
1763 if (!map_open_params_to_ntcreate(
1764 smb_fname->base_name, deny_mode, OPENX_FILE_EXISTS_OPEN,
1765 &access_mask, &share_mode, &create_disposition,
1767 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1771 status = SMB_VFS_CREATE_FILE(
1774 0, /* root_dir_fid */
1775 smb_fname, /* fname */
1776 access_mask, /* access_mask */
1777 share_mode, /* share_access */
1778 create_disposition, /* create_disposition*/
1779 create_options, /* create_options */
1780 dos_attr, /* file_attributes */
1781 oplock_request, /* oplock_request */
1782 0, /* allocation_size */
1788 if (!NT_STATUS_IS_OK(status)) {
1789 if (open_was_deferred(req->mid)) {
1790 /* We have re-scheduled this call. */
1793 reply_openerror(req, status);
1797 size = smb_fname->st.st_ex_size;
1798 fattr = dos_mode(conn, smb_fname);
1800 /* Deal with other possible opens having a modified
1802 if (ask_sharemode) {
1803 struct timespec write_time_ts;
1805 ZERO_STRUCT(write_time_ts);
1806 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1807 if (!null_timespec(write_time_ts)) {
1808 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1812 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1815 DEBUG(3,("attempt to open a directory %s\n",
1817 close_file(req, fsp, ERROR_CLOSE);
1818 reply_doserror(req, ERRDOS,ERRnoaccess);
1822 reply_outbuf(req, 7, 0);
1823 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1824 SSVAL(req->outbuf,smb_vwv1,fattr);
1825 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1826 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1828 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1830 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1831 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1833 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1834 SCVAL(req->outbuf,smb_flg,
1835 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1838 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1839 SCVAL(req->outbuf,smb_flg,
1840 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1843 TALLOC_FREE(smb_fname);
1844 END_PROFILE(SMBopen);
1848 /****************************************************************************
1849 Reply to an open and X.
1850 ****************************************************************************/
1852 void reply_open_and_X(struct smb_request *req)
1854 connection_struct *conn = req->conn;
1855 struct smb_filename *smb_fname = NULL;
1860 /* Breakout the oplock request bits so we can set the
1861 reply bits separately. */
1862 int ex_oplock_request;
1863 int core_oplock_request;
1866 int smb_sattr = SVAL(req->vwv+4, 0);
1867 uint32 smb_time = make_unix_date3(req->vwv+6);
1875 uint64_t allocation_size;
1876 ssize_t retval = -1;
1879 uint32 create_disposition;
1880 uint32 create_options = 0;
1881 TALLOC_CTX *ctx = talloc_tos();
1883 START_PROFILE(SMBopenX);
1885 if (req->wct < 15) {
1886 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1890 open_flags = SVAL(req->vwv+2, 0);
1891 deny_mode = SVAL(req->vwv+3, 0);
1892 smb_attr = SVAL(req->vwv+5, 0);
1893 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1894 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1895 oplock_request = ex_oplock_request | core_oplock_request;
1896 smb_ofun = SVAL(req->vwv+8, 0);
1897 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1899 /* If it's an IPC, pass off the pipe handler. */
1901 if (lp_nt_pipe_support()) {
1902 reply_open_pipe_and_X(conn, req);
1904 reply_doserror(req, ERRSRV, ERRaccess);
1909 /* XXXX we need to handle passed times, sattr and flags */
1910 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1911 STR_TERMINATE, &status);
1912 if (!NT_STATUS_IS_OK(status)) {
1913 reply_nterror(req, status);
1917 status = filename_convert(ctx,
1919 req->flags2 & FLAGS2_DFS_PATHNAMES,
1923 if (!NT_STATUS_IS_OK(status)) {
1924 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1925 reply_botherror(req,
1926 NT_STATUS_PATH_NOT_COVERED,
1927 ERRSRV, ERRbadpath);
1930 reply_nterror(req, status);
1934 if (!map_open_params_to_ntcreate(
1935 smb_fname->base_name, deny_mode, smb_ofun, &access_mask,
1936 &share_mode, &create_disposition, &create_options)) {
1937 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1941 status = SMB_VFS_CREATE_FILE(
1944 0, /* root_dir_fid */
1945 smb_fname, /* fname */
1946 access_mask, /* access_mask */
1947 share_mode, /* share_access */
1948 create_disposition, /* create_disposition*/
1949 create_options, /* create_options */
1950 smb_attr, /* file_attributes */
1951 oplock_request, /* oplock_request */
1952 0, /* allocation_size */
1956 &smb_action); /* pinfo */
1958 if (!NT_STATUS_IS_OK(status)) {
1959 if (open_was_deferred(req->mid)) {
1960 /* We have re-scheduled this call. */
1963 reply_openerror(req, status);
1967 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1968 if the file is truncated or created. */
1969 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1970 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1971 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1972 close_file(req, fsp, ERROR_CLOSE);
1973 reply_nterror(req, NT_STATUS_DISK_FULL);
1976 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1978 close_file(req, fsp, ERROR_CLOSE);
1979 reply_nterror(req, NT_STATUS_DISK_FULL);
1982 smb_fname->st.st_ex_size =
1983 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1986 fattr = dos_mode(conn, smb_fname);
1987 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1989 close_file(req, fsp, ERROR_CLOSE);
1990 reply_doserror(req, ERRDOS, ERRnoaccess);
1994 /* If the caller set the extended oplock request bit
1995 and we granted one (by whatever means) - set the
1996 correct bit for extended oplock reply.
1999 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2000 smb_action |= EXTENDED_OPLOCK_GRANTED;
2003 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2004 smb_action |= EXTENDED_OPLOCK_GRANTED;
2007 /* If the caller set the core oplock request bit
2008 and we granted one (by whatever means) - set the
2009 correct bit for core oplock reply.
2012 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2013 reply_outbuf(req, 19, 0);
2015 reply_outbuf(req, 15, 0);
2018 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2019 SCVAL(req->outbuf, smb_flg,
2020 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2023 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2024 SCVAL(req->outbuf, smb_flg,
2025 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2028 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2029 SSVAL(req->outbuf,smb_vwv3,fattr);
2030 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2031 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2033 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2035 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2036 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2037 SSVAL(req->outbuf,smb_vwv11,smb_action);
2039 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2040 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2045 TALLOC_FREE(smb_fname);
2046 END_PROFILE(SMBopenX);
2050 /****************************************************************************
2051 Reply to a SMBulogoffX.
2052 ****************************************************************************/
2054 void reply_ulogoffX(struct smb_request *req)
2056 struct smbd_server_connection *sconn = smbd_server_conn;
2059 START_PROFILE(SMBulogoffX);
2061 vuser = get_valid_user_struct(sconn, req->vuid);
2064 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2068 /* in user level security we are supposed to close any files
2069 open by this user */
2070 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2071 file_close_user(req->vuid);
2074 invalidate_vuid(sconn, req->vuid);
2076 reply_outbuf(req, 2, 0);
2078 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2080 END_PROFILE(SMBulogoffX);
2081 req->vuid = UID_FIELD_INVALID;
2085 /****************************************************************************
2086 Reply to a mknew or a create.
2087 ****************************************************************************/
2089 void reply_mknew(struct smb_request *req)
2091 connection_struct *conn = req->conn;
2092 struct smb_filename *smb_fname = NULL;
2095 struct smb_file_time ft;
2097 int oplock_request = 0;
2099 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2100 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2101 uint32 create_disposition;
2102 uint32 create_options = 0;
2103 TALLOC_CTX *ctx = talloc_tos();
2105 START_PROFILE(SMBcreate);
2109 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2113 fattr = SVAL(req->vwv+0, 0);
2114 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2117 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2119 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2120 STR_TERMINATE, &status);
2121 if (!NT_STATUS_IS_OK(status)) {
2122 reply_nterror(req, status);
2126 status = filename_convert(ctx,
2128 req->flags2 & FLAGS2_DFS_PATHNAMES,
2132 if (!NT_STATUS_IS_OK(status)) {
2133 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2134 reply_botherror(req,
2135 NT_STATUS_PATH_NOT_COVERED,
2136 ERRSRV, ERRbadpath);
2139 reply_nterror(req, status);
2143 if (fattr & aVOLID) {
2144 DEBUG(0,("Attempt to create file (%s) with volid set - "
2145 "please report this\n",
2146 smb_fname_str_dbg(smb_fname)));
2149 if(req->cmd == SMBmknew) {
2150 /* We should fail if file exists. */
2151 create_disposition = FILE_CREATE;
2153 /* Create if file doesn't exist, truncate if it does. */
2154 create_disposition = FILE_OVERWRITE_IF;
2157 status = SMB_VFS_CREATE_FILE(
2160 0, /* root_dir_fid */
2161 smb_fname, /* fname */
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 */
2174 if (!NT_STATUS_IS_OK(status)) {
2175 if (open_was_deferred(req->mid)) {
2176 /* We have re-scheduled this call. */
2179 reply_openerror(req, status);
2183 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2184 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2185 if (!NT_STATUS_IS_OK(status)) {
2186 END_PROFILE(SMBcreate);
2190 reply_outbuf(req, 1, 0);
2191 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2193 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2194 SCVAL(req->outbuf,smb_flg,
2195 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2198 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2199 SCVAL(req->outbuf,smb_flg,
2200 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2203 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2204 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2205 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2206 (unsigned int)fattr));
2209 TALLOC_FREE(smb_fname);
2210 END_PROFILE(SMBcreate);
2214 /****************************************************************************
2215 Reply to a create temporary file.
2216 ****************************************************************************/
2218 void reply_ctemp(struct smb_request *req)
2220 connection_struct *conn = req->conn;
2221 struct smb_filename *smb_fname = NULL;
2229 TALLOC_CTX *ctx = talloc_tos();
2231 START_PROFILE(SMBctemp);
2234 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2238 fattr = SVAL(req->vwv+0, 0);
2239 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2241 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2242 STR_TERMINATE, &status);
2243 if (!NT_STATUS_IS_OK(status)) {
2244 reply_nterror(req, status);
2248 fname = talloc_asprintf(ctx,
2252 fname = talloc_strdup(ctx, "TMXXXXXX");
2256 reply_nterror(req, NT_STATUS_NO_MEMORY);
2260 status = filename_convert(ctx, conn,
2261 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 tmpfd = mkstemp(smb_fname->base_name);
2277 reply_nterror(req, map_nt_error_from_unix(errno));
2281 SMB_VFS_STAT(conn, smb_fname);
2283 /* We should fail if file does not exist. */
2284 status = SMB_VFS_CREATE_FILE(
2287 0, /* root_dir_fid */
2288 smb_fname, /* fname */
2289 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2290 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2291 FILE_OPEN, /* create_disposition*/
2292 0, /* create_options */
2293 fattr, /* file_attributes */
2294 oplock_request, /* oplock_request */
2295 0, /* allocation_size */
2301 /* close fd from mkstemp() */
2304 if (!NT_STATUS_IS_OK(status)) {
2305 if (open_was_deferred(req->mid)) {
2306 /* We have re-scheduled this call. */
2309 reply_openerror(req, status);
2313 reply_outbuf(req, 1, 0);
2314 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2316 /* the returned filename is relative to the directory */
2317 s = strrchr_m(fsp->fsp_name->base_name, '/');
2319 s = fsp->fsp_name->base_name;
2325 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2326 thing in the byte section. JRA */
2327 SSVALS(p, 0, -1); /* what is this? not in spec */
2329 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2331 reply_nterror(req, NT_STATUS_NO_MEMORY);
2335 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2336 SCVAL(req->outbuf, smb_flg,
2337 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2340 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2341 SCVAL(req->outbuf, smb_flg,
2342 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2345 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2346 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2347 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2349 TALLOC_FREE(smb_fname);
2350 END_PROFILE(SMBctemp);
2354 /*******************************************************************
2355 Check if a user is allowed to rename a file.
2356 ********************************************************************/
2358 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2359 uint16 dirtype, SMB_STRUCT_STAT *pst)
2363 if (!CAN_WRITE(conn)) {
2364 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2367 fmode = dos_mode(conn, fsp->fsp_name);
2368 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2369 return NT_STATUS_NO_SUCH_FILE;
2372 if (S_ISDIR(pst->st_ex_mode)) {
2373 if (fsp->posix_open) {
2374 return NT_STATUS_OK;
2377 /* If no pathnames are open below this
2378 directory, allow the rename. */
2380 if (file_find_subpath(fsp)) {
2381 return NT_STATUS_ACCESS_DENIED;
2383 return NT_STATUS_OK;
2386 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2387 return NT_STATUS_OK;
2390 return NT_STATUS_ACCESS_DENIED;
2393 /*******************************************************************
2394 * unlink a file with all relevant access checks
2395 *******************************************************************/
2397 static NTSTATUS do_unlink(connection_struct *conn,
2398 struct smb_request *req,
2399 struct smb_filename *smb_fname,
2404 uint32 dirtype_orig = dirtype;
2407 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2408 smb_fname_str_dbg(smb_fname),
2411 if (!CAN_WRITE(conn)) {
2412 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2415 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
2416 return map_nt_error_from_unix(errno);
2419 fattr = dos_mode(conn, smb_fname);
2421 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2422 dirtype = aDIR|aARCH|aRONLY;
2425 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2427 return NT_STATUS_NO_SUCH_FILE;
2430 if (!dir_check_ftype(conn, fattr, dirtype)) {
2432 return NT_STATUS_FILE_IS_A_DIRECTORY;
2434 return NT_STATUS_NO_SUCH_FILE;
2437 if (dirtype_orig & 0x8000) {
2438 /* These will never be set for POSIX. */
2439 return NT_STATUS_NO_SUCH_FILE;
2443 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2444 return NT_STATUS_FILE_IS_A_DIRECTORY;
2447 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2448 return NT_STATUS_NO_SUCH_FILE;
2451 if (dirtype & 0xFF00) {
2452 /* These will never be set for POSIX. */
2453 return NT_STATUS_NO_SUCH_FILE;
2458 return NT_STATUS_NO_SUCH_FILE;
2461 /* Can't delete a directory. */
2463 return NT_STATUS_FILE_IS_A_DIRECTORY;
2468 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2469 return NT_STATUS_OBJECT_NAME_INVALID;
2470 #endif /* JRATEST */
2472 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2474 On a Windows share, a file with read-only dosmode can be opened with
2475 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2476 fails with NT_STATUS_CANNOT_DELETE error.
2478 This semantic causes a problem that a user can not
2479 rename a file with read-only dosmode on a Samba share
2480 from a Windows command prompt (i.e. cmd.exe, but can rename
2481 from Windows Explorer).
2484 if (!lp_delete_readonly(SNUM(conn))) {
2485 if (fattr & aRONLY) {
2486 return NT_STATUS_CANNOT_DELETE;
2490 /* On open checks the open itself will check the share mode, so
2491 don't do it here as we'll get it wrong. */
2493 status = SMB_VFS_CREATE_FILE
2496 0, /* root_dir_fid */
2497 smb_fname, /* fname */
2498 DELETE_ACCESS, /* access_mask */
2499 FILE_SHARE_NONE, /* share_access */
2500 FILE_OPEN, /* create_disposition*/
2501 FILE_NON_DIRECTORY_FILE, /* create_options */
2502 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2503 0, /* oplock_request */
2504 0, /* allocation_size */
2510 if (!NT_STATUS_IS_OK(status)) {
2511 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2512 nt_errstr(status)));
2516 /* The set is across all open files on this dev/inode pair. */
2517 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2518 close_file(req, fsp, NORMAL_CLOSE);
2519 return NT_STATUS_ACCESS_DENIED;
2522 return close_file(req, fsp, NORMAL_CLOSE);
2525 /****************************************************************************
2526 The guts of the unlink command, split out so it may be called by the NT SMB
2528 ****************************************************************************/
2530 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2531 uint32 dirtype, const char *name_in, bool has_wild)
2533 struct smb_filename *smb_fname = NULL;
2534 char *fname_dir = NULL;
2535 char *fname_mask = NULL;
2537 NTSTATUS status = NT_STATUS_OK;
2538 TALLOC_CTX *ctx = talloc_tos();
2540 status = unix_convert(ctx, conn, name_in, &smb_fname,
2541 has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
2542 if (!NT_STATUS_IS_OK(status)) {
2546 /* Split up the directory from the filename/mask. */
2547 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2548 &fname_dir, &fname_mask);
2549 if (!NT_STATUS_IS_OK(status)) {
2554 * We should only check the mangled cache
2555 * here if unix_convert failed. This means
2556 * that the path in 'mask' doesn't exist
2557 * on the file system and so we need to look
2558 * for a possible mangle. This patch from
2559 * Tine Smukavec <valentin.smukavec@hermes.si>.
2562 if (!VALID_STAT(smb_fname->st) &&
2563 mangle_is_mangled(fname_mask, conn->params)) {
2564 char *new_mask = NULL;
2565 mangle_lookup_name_from_8_3(ctx, fname_mask,
2566 &new_mask, conn->params);
2568 TALLOC_FREE(fname_mask);
2569 fname_mask = new_mask;
2576 * Only one file needs to be unlinked. Append the mask back
2577 * onto the directory.
2579 TALLOC_FREE(smb_fname->base_name);
2580 smb_fname->base_name = talloc_asprintf(smb_fname,
2584 if (!smb_fname->base_name) {
2585 status = NT_STATUS_NO_MEMORY;
2589 dirtype = FILE_ATTRIBUTE_NORMAL;
2592 status = check_name(conn, smb_fname->base_name);
2593 if (!NT_STATUS_IS_OK(status)) {
2597 status = do_unlink(conn, req, smb_fname, dirtype);
2598 if (!NT_STATUS_IS_OK(status)) {
2604 struct smb_Dir *dir_hnd = NULL;
2608 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2609 status = NT_STATUS_OBJECT_NAME_INVALID;
2613 if (strequal(fname_mask,"????????.???")) {
2614 TALLOC_FREE(fname_mask);
2615 fname_mask = talloc_strdup(ctx, "*");
2617 status = NT_STATUS_NO_MEMORY;
2622 status = check_name(conn, fname_dir);
2623 if (!NT_STATUS_IS_OK(status)) {
2627 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2629 if (dir_hnd == NULL) {
2630 status = map_nt_error_from_unix(errno);
2634 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2635 the pattern matches against the long name, otherwise the short name
2636 We don't implement this yet XXXX
2639 status = NT_STATUS_NO_SUCH_FILE;
2641 while ((dname = ReadDirName(dir_hnd, &offset,
2643 TALLOC_CTX *frame = talloc_stackframe();
2645 if (!is_visible_file(conn, fname_dir, dname,
2646 &smb_fname->st, true)) {
2651 /* Quick check for "." and ".." */
2652 if (ISDOT(dname) || ISDOTDOT(dname)) {
2657 if(!mask_match(dname, fname_mask,
2658 conn->case_sensitive)) {
2663 TALLOC_FREE(smb_fname->base_name);
2664 smb_fname->base_name =
2665 talloc_asprintf(smb_fname, "%s/%s",
2668 if (!smb_fname->base_name) {
2669 TALLOC_FREE(dir_hnd);
2670 status = NT_STATUS_NO_MEMORY;
2675 status = check_name(conn, smb_fname->base_name);
2676 if (!NT_STATUS_IS_OK(status)) {
2677 TALLOC_FREE(dir_hnd);
2682 status = do_unlink(conn, req, smb_fname, dirtype);
2683 if (!NT_STATUS_IS_OK(status)) {
2689 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2690 smb_fname->base_name));
2694 TALLOC_FREE(dir_hnd);
2697 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2698 status = map_nt_error_from_unix(errno);
2702 TALLOC_FREE(smb_fname);
2703 TALLOC_FREE(fname_dir);
2704 TALLOC_FREE(fname_mask);
2708 /****************************************************************************
2710 ****************************************************************************/
2712 void reply_unlink(struct smb_request *req)
2714 connection_struct *conn = req->conn;
2718 bool path_contains_wcard = False;
2719 TALLOC_CTX *ctx = talloc_tos();
2721 START_PROFILE(SMBunlink);
2724 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2725 END_PROFILE(SMBunlink);
2729 dirtype = SVAL(req->vwv+0, 0);
2731 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2732 STR_TERMINATE, &status,
2733 &path_contains_wcard);
2734 if (!NT_STATUS_IS_OK(status)) {
2735 reply_nterror(req, status);
2736 END_PROFILE(SMBunlink);
2740 status = resolve_dfspath_wcard(ctx, conn,
2741 req->flags2 & FLAGS2_DFS_PATHNAMES,
2744 &path_contains_wcard);
2745 if (!NT_STATUS_IS_OK(status)) {
2746 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2747 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2748 ERRSRV, ERRbadpath);
2749 END_PROFILE(SMBunlink);
2752 reply_nterror(req, status);
2753 END_PROFILE(SMBunlink);
2757 DEBUG(3,("reply_unlink : %s\n",name));
2759 status = unlink_internals(conn, req, dirtype, name,
2760 path_contains_wcard);
2761 if (!NT_STATUS_IS_OK(status)) {
2762 if (open_was_deferred(req->mid)) {
2763 /* We have re-scheduled this call. */
2764 END_PROFILE(SMBunlink);
2767 reply_nterror(req, status);
2768 END_PROFILE(SMBunlink);
2772 reply_outbuf(req, 0, 0);
2773 END_PROFILE(SMBunlink);
2778 /****************************************************************************
2780 ****************************************************************************/
2782 static void fail_readraw(void)
2784 const char *errstr = talloc_asprintf(talloc_tos(),
2785 "FAIL ! reply_readbraw: socket write fail (%s)",
2790 exit_server_cleanly(errstr);
2793 /****************************************************************************
2794 Fake (read/write) sendfile. Returns -1 on read or write fail.
2795 ****************************************************************************/
2797 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2801 size_t tosend = nread;
2808 bufsize = MIN(nread, 65536);
2810 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2814 while (tosend > 0) {
2818 if (tosend > bufsize) {
2823 ret = read_file(fsp,buf,startpos,cur_read);
2829 /* If we had a short read, fill with zeros. */
2830 if (ret < cur_read) {
2831 memset(buf + ret, '\0', cur_read - ret);
2834 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2839 startpos += cur_read;
2843 return (ssize_t)nread;
2846 #if defined(WITH_SENDFILE)
2847 /****************************************************************************
2848 Deal with the case of sendfile reading less bytes from the file than
2849 requested. Fill with zeros (all we can do).
2850 ****************************************************************************/
2852 static void sendfile_short_send(files_struct *fsp,
2857 #define SHORT_SEND_BUFSIZE 1024
2858 if (nread < headersize) {
2859 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2860 "header for file %s (%s). Terminating\n",
2861 fsp_str_dbg(fsp), strerror(errno)));
2862 exit_server_cleanly("sendfile_short_send failed");
2865 nread -= headersize;
2867 if (nread < smb_maxcnt) {
2868 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2870 exit_server_cleanly("sendfile_short_send: "
2874 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2875 "with zeros !\n", fsp_str_dbg(fsp)));
2877 while (nread < smb_maxcnt) {
2879 * We asked for the real file size and told sendfile
2880 * to not go beyond the end of the file. But it can
2881 * happen that in between our fstat call and the
2882 * sendfile call the file was truncated. This is very
2883 * bad because we have already announced the larger
2884 * number of bytes to the client.
2886 * The best we can do now is to send 0-bytes, just as
2887 * a read from a hole in a sparse file would do.
2889 * This should happen rarely enough that I don't care
2890 * about efficiency here :-)
2894 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2895 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2896 exit_server_cleanly("sendfile_short_send: "
2897 "write_data failed");
2904 #endif /* defined WITH_SENDFILE */
2906 /****************************************************************************
2907 Return a readbraw error (4 bytes of zero).
2908 ****************************************************************************/
2910 static void reply_readbraw_error(void)
2914 if (write_data(smbd_server_fd(),header,4) != 4) {
2919 /****************************************************************************
2920 Use sendfile in readbraw.
2921 ****************************************************************************/
2923 static void send_file_readbraw(connection_struct *conn,
2924 struct smb_request *req,
2930 char *outbuf = NULL;
2933 #if defined(WITH_SENDFILE)
2935 * We can only use sendfile on a non-chained packet
2936 * but we can use on a non-oplocked file. tridge proved this
2937 * on a train in Germany :-). JRA.
2938 * reply_readbraw has already checked the length.
2941 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2942 (fsp->wcp == NULL) &&
2943 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2944 ssize_t sendfile_read = -1;
2946 DATA_BLOB header_blob;
2948 _smb_setlen(header,nread);
2949 header_blob = data_blob_const(header, 4);
2951 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2952 &header_blob, startpos, nread)) == -1) {
2953 /* Returning ENOSYS means no data at all was sent.
2954 * Do this as a normal read. */
2955 if (errno == ENOSYS) {
2956 goto normal_readbraw;
2960 * Special hack for broken Linux with no working sendfile. If we
2961 * return EINTR we sent the header but not the rest of the data.
2962 * Fake this up by doing read/write calls.
2964 if (errno == EINTR) {
2965 /* Ensure we don't do this again. */
2966 set_use_sendfile(SNUM(conn), False);
2967 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2969 if (fake_sendfile(fsp, startpos, nread) == -1) {
2970 DEBUG(0,("send_file_readbraw: "
2971 "fake_sendfile failed for "
2975 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2980 DEBUG(0,("send_file_readbraw: sendfile failed for "
2981 "file %s (%s). Terminating\n",
2982 fsp_str_dbg(fsp), strerror(errno)));
2983 exit_server_cleanly("send_file_readbraw sendfile failed");
2984 } else if (sendfile_read == 0) {
2986 * Some sendfile implementations return 0 to indicate
2987 * that there was a short read, but nothing was
2988 * actually written to the socket. In this case,
2989 * fallback to the normal read path so the header gets
2990 * the correct byte count.
2992 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2993 "bytes falling back to the normal read: "
2994 "%s\n", fsp_str_dbg(fsp)));
2995 goto normal_readbraw;
2998 /* Deal with possible short send. */
2999 if (sendfile_read != 4+nread) {
3000 sendfile_short_send(fsp, sendfile_read, 4, nread);
3008 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3010 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3011 (unsigned)(nread+4)));
3012 reply_readbraw_error();
3017 ret = read_file(fsp,outbuf+4,startpos,nread);
3018 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3027 _smb_setlen(outbuf,ret);
3028 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3031 TALLOC_FREE(outbuf);
3034 /****************************************************************************
3035 Reply to a readbraw (core+ protocol).
3036 ****************************************************************************/
3038 void reply_readbraw(struct smb_request *req)
3040 connection_struct *conn = req->conn;
3041 ssize_t maxcount,mincount;
3045 struct lock_struct lock;
3049 START_PROFILE(SMBreadbraw);
3051 if (srv_is_signing_active(smbd_server_conn) ||
3052 is_encrypted_packet(req->inbuf)) {
3053 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3054 "raw reads/writes are disallowed.");
3058 reply_readbraw_error();
3059 END_PROFILE(SMBreadbraw);
3064 * Special check if an oplock break has been issued
3065 * and the readraw request croses on the wire, we must
3066 * return a zero length response here.
3069 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3072 * We have to do a check_fsp by hand here, as
3073 * we must always return 4 zero bytes on error,
3077 if (!fsp || !conn || conn != fsp->conn ||
3078 req->vuid != fsp->vuid ||
3079 fsp->is_directory || fsp->fh->fd == -1) {
3081 * fsp could be NULL here so use the value from the packet. JRA.
3083 DEBUG(3,("reply_readbraw: fnum %d not valid "
3085 (int)SVAL(req->vwv+0, 0)));
3086 reply_readbraw_error();
3087 END_PROFILE(SMBreadbraw);
3091 /* Do a "by hand" version of CHECK_READ. */
3092 if (!(fsp->can_read ||
3093 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3094 (fsp->access_mask & FILE_EXECUTE)))) {
3095 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3096 (int)SVAL(req->vwv+0, 0)));
3097 reply_readbraw_error();
3098 END_PROFILE(SMBreadbraw);
3102 flush_write_cache(fsp, READRAW_FLUSH);
3104 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3105 if(req->wct == 10) {
3107 * This is a large offset (64 bit) read.
3109 #ifdef LARGE_SMB_OFF_T
3111 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3113 #else /* !LARGE_SMB_OFF_T */
3116 * Ensure we haven't been sent a >32 bit offset.
3119 if(IVAL(req->vwv+8, 0) != 0) {
3120 DEBUG(0,("reply_readbraw: large offset "
3121 "(%x << 32) used and we don't support "
3122 "64 bit offsets.\n",
3123 (unsigned int)IVAL(req->vwv+8, 0) ));
3124 reply_readbraw_error();
3125 END_PROFILE(SMBreadbraw);
3129 #endif /* LARGE_SMB_OFF_T */
3132 DEBUG(0,("reply_readbraw: negative 64 bit "
3133 "readraw offset (%.0f) !\n",
3134 (double)startpos ));
3135 reply_readbraw_error();
3136 END_PROFILE(SMBreadbraw);
3141 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3142 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3144 /* ensure we don't overrun the packet size */
3145 maxcount = MIN(65535,maxcount);
3147 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3148 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3151 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3152 reply_readbraw_error();
3153 END_PROFILE(SMBreadbraw);
3157 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3158 size = st.st_ex_size;
3161 if (startpos >= size) {
3164 nread = MIN(maxcount,(size - startpos));
3167 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3168 if (nread < mincount)
3172 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3173 "min=%lu nread=%lu\n",
3174 fsp->fnum, (double)startpos,
3175 (unsigned long)maxcount,
3176 (unsigned long)mincount,
3177 (unsigned long)nread ) );
3179 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3181 DEBUG(5,("reply_readbraw finished\n"));
3183 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3185 END_PROFILE(SMBreadbraw);
3190 #define DBGC_CLASS DBGC_LOCKING
3192 /****************************************************************************
3193 Reply to a lockread (core+ protocol).
3194 ****************************************************************************/
3196 void reply_lockread(struct smb_request *req)
3198 connection_struct *conn = req->conn;
3205 struct byte_range_lock *br_lck = NULL;
3207 struct smbd_server_connection *sconn = smbd_server_conn;
3209 START_PROFILE(SMBlockread);
3212 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3213 END_PROFILE(SMBlockread);
3217 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3219 if (!check_fsp(conn, req, fsp)) {
3220 END_PROFILE(SMBlockread);
3224 if (!CHECK_READ(fsp,req)) {
3225 reply_doserror(req, ERRDOS, ERRbadaccess);
3226 END_PROFILE(SMBlockread);
3230 numtoread = SVAL(req->vwv+1, 0);
3231 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3233 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3235 reply_outbuf(req, 5, numtoread + 3);
3237 data = smb_buf(req->outbuf) + 3;
3240 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3241 * protocol request that predates the read/write lock concept.
3242 * Thus instead of asking for a read lock here we need to ask
3243 * for a write lock. JRA.
3244 * Note that the requested lock size is unaffected by max_recv.
3247 br_lck = do_lock(smbd_messaging_context(),
3250 (uint64_t)numtoread,
3254 False, /* Non-blocking lock. */
3258 TALLOC_FREE(br_lck);
3260 if (NT_STATUS_V(status)) {
3261 reply_nterror(req, status);
3262 END_PROFILE(SMBlockread);
3267 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3270 if (numtoread > sconn->smb1.negprot.max_recv) {
3271 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3272 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3273 (unsigned int)numtoread,
3274 (unsigned int)sconn->smb1.negprot.max_recv));
3275 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3277 nread = read_file(fsp,data,startpos,numtoread);
3280 reply_nterror(req, map_nt_error_from_unix(errno));
3281 END_PROFILE(SMBlockread);
3285 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3287 SSVAL(req->outbuf,smb_vwv0,nread);
3288 SSVAL(req->outbuf,smb_vwv5,nread+3);
3289 p = smb_buf(req->outbuf);
3290 SCVAL(p,0,0); /* pad byte. */
3293 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3294 fsp->fnum, (int)numtoread, (int)nread));
3296 END_PROFILE(SMBlockread);
3301 #define DBGC_CLASS DBGC_ALL
3303 /****************************************************************************
3305 ****************************************************************************/
3307 void reply_read(struct smb_request *req)
3309 connection_struct *conn = req->conn;
3316 struct lock_struct lock;
3317 struct smbd_server_connection *sconn = smbd_server_conn;
3319 START_PROFILE(SMBread);
3322 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3323 END_PROFILE(SMBread);
3327 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3329 if (!check_fsp(conn, req, fsp)) {
3330 END_PROFILE(SMBread);
3334 if (!CHECK_READ(fsp,req)) {
3335 reply_doserror(req, ERRDOS, ERRbadaccess);
3336 END_PROFILE(SMBread);
3340 numtoread = SVAL(req->vwv+1, 0);
3341 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3343 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3346 * The requested read size cannot be greater than max_recv. JRA.
3348 if (numtoread > sconn->smb1.negprot.max_recv) {
3349 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3350 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3351 (unsigned int)numtoread,
3352 (unsigned int)sconn->smb1.negprot.max_recv));
3353 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3356 reply_outbuf(req, 5, numtoread+3);
3358 data = smb_buf(req->outbuf) + 3;
3360 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3361 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3364 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3365 reply_doserror(req, ERRDOS,ERRlock);
3366 END_PROFILE(SMBread);
3371 nread = read_file(fsp,data,startpos,numtoread);
3374 reply_nterror(req, map_nt_error_from_unix(errno));
3378 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3380 SSVAL(req->outbuf,smb_vwv0,nread);
3381 SSVAL(req->outbuf,smb_vwv5,nread+3);
3382 SCVAL(smb_buf(req->outbuf),0,1);
3383 SSVAL(smb_buf(req->outbuf),1,nread);
3385 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3386 fsp->fnum, (int)numtoread, (int)nread ) );
3389 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3391 END_PROFILE(SMBread);
3395 /****************************************************************************
3397 ****************************************************************************/
3399 static int setup_readX_header(struct smb_request *req, char *outbuf,
3405 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3406 data = smb_buf(outbuf);
3408 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3410 SCVAL(outbuf,smb_vwv0,0xFF);
3411 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3412 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3413 SSVAL(outbuf,smb_vwv6,
3415 + 1 /* the wct field */
3416 + 12 * sizeof(uint16_t) /* vwv */
3417 + 2); /* the buflen field */
3418 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3419 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3420 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3421 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3425 /****************************************************************************
3426 Reply to a read and X - possibly using sendfile.
3427 ****************************************************************************/
3429 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3430 files_struct *fsp, SMB_OFF_T startpos,
3433 SMB_STRUCT_STAT sbuf;
3435 struct lock_struct lock;
3436 int saved_errno = 0;
3438 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3439 reply_nterror(req, map_nt_error_from_unix(errno));
3443 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3444 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3447 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3448 reply_doserror(req, ERRDOS, ERRlock);
3452 if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
3453 || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
3455 * We already know that we would do a short read, so don't
3456 * try the sendfile() path.
3458 goto nosendfile_read;
3461 #if defined(WITH_SENDFILE)
3463 * We can only use sendfile on a non-chained packet
3464 * but we can use on a non-oplocked file. tridge proved this
3465 * on a train in Germany :-). JRA.
3468 if (!req_is_in_chain(req) &&
3469 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3470 (fsp->wcp == NULL) &&
3471 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3472 uint8 headerbuf[smb_size + 12 * 2];
3476 * Set up the packet header before send. We
3477 * assume here the sendfile will work (get the
3478 * correct amount of data).
3481 header = data_blob_const(headerbuf, sizeof(headerbuf));
3483 construct_reply_common_req(req, (char *)headerbuf);
3484 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3486 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3487 /* Returning ENOSYS means no data at all was sent.
3488 Do this as a normal read. */
3489 if (errno == ENOSYS) {
3494 * Special hack for broken Linux with no working sendfile. If we
3495 * return EINTR we sent the header but not the rest of the data.
3496 * Fake this up by doing read/write calls.
3499 if (errno == EINTR) {
3500 /* Ensure we don't do this again. */
3501 set_use_sendfile(SNUM(conn), False);
3502 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3503 nread = fake_sendfile(fsp, startpos,
3506 DEBUG(0,("send_file_readX: "
3507 "fake_sendfile failed for "
3511 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3513 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3514 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3515 /* No outbuf here means successful sendfile. */
3519 DEBUG(0,("send_file_readX: sendfile failed for file "
3520 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3522 exit_server_cleanly("send_file_readX sendfile failed");
3523 } else if (nread == 0) {
3525 * Some sendfile implementations return 0 to indicate
3526 * that there was a short read, but nothing was
3527 * actually written to the socket. In this case,
3528 * fallback to the normal read path so the header gets
3529 * the correct byte count.
3531 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3532 "falling back to the normal read: %s\n",
3537 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3538 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3540 /* Deal with possible short send. */
3541 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3542 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3544 /* No outbuf here means successful sendfile. */
3545 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3546 SMB_PERFCOUNT_END(&req->pcd);
3554 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3555 uint8 headerbuf[smb_size + 2*12];
3557 construct_reply_common_req(req, (char *)headerbuf);
3558 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3560 /* Send out the header. */
3561 if (write_data(smbd_server_fd(), (char *)headerbuf,
3562 sizeof(headerbuf)) != sizeof(headerbuf)) {
3563 DEBUG(0,("send_file_readX: write_data failed for file "
3564 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3566 exit_server_cleanly("send_file_readX sendfile failed");
3568 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3570 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3571 "file %s (%s).\n", fsp_str_dbg(fsp),
3573 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3580 reply_outbuf(req, 12, smb_maxcnt);
3582 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3583 saved_errno = errno;
3585 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3588 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3592 setup_readX_header(req, (char *)req->outbuf, nread);
3594 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3595 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3601 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3602 TALLOC_FREE(req->outbuf);
3606 /****************************************************************************
3607 Reply to a read and X.
3608 ****************************************************************************/
3610 void reply_read_and_X(struct smb_request *req)
3612 connection_struct *conn = req->conn;
3616 bool big_readX = False;
3618 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3621 START_PROFILE(SMBreadX);
3623 if ((req->wct != 10) && (req->wct != 12)) {
3624 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3628 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3629 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3630 smb_maxcnt = SVAL(req->vwv+5, 0);
3632 /* If it's an IPC, pass off the pipe handler. */
3634 reply_pipe_read_and_X(req);
3635 END_PROFILE(SMBreadX);
3639 if (!check_fsp(conn, req, fsp)) {
3640 END_PROFILE(SMBreadX);
3644 if (!CHECK_READ(fsp,req)) {
3645 reply_doserror(req, ERRDOS,ERRbadaccess);
3646 END_PROFILE(SMBreadX);
3650 if (global_client_caps & CAP_LARGE_READX) {
3651 size_t upper_size = SVAL(req->vwv+7, 0);
3652 smb_maxcnt |= (upper_size<<16);
3653 if (upper_size > 1) {
3654 /* Can't do this on a chained packet. */
3655 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3656 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3657 END_PROFILE(SMBreadX);
3660 /* We currently don't do this on signed or sealed data. */
3661 if (srv_is_signing_active(smbd_server_conn) ||
3662 is_encrypted_packet(req->inbuf)) {
3663 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3664 END_PROFILE(SMBreadX);
3667 /* Is there room in the reply for this data ? */
3668 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3670 NT_STATUS_INVALID_PARAMETER);
3671 END_PROFILE(SMBreadX);
3678 if (req->wct == 12) {
3679 #ifdef LARGE_SMB_OFF_T
3681 * This is a large offset (64 bit) read.
3683 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3685 #else /* !LARGE_SMB_OFF_T */
3688 * Ensure we haven't been sent a >32 bit offset.
3691 if(IVAL(req->vwv+10, 0) != 0) {
3692 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3693 "used and we don't support 64 bit offsets.\n",
3694 (unsigned int)IVAL(req->vwv+10, 0) ));
3695 END_PROFILE(SMBreadX);
3696 reply_doserror(req, ERRDOS, ERRbadaccess);
3700 #endif /* LARGE_SMB_OFF_T */
3705 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3709 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3712 END_PROFILE(SMBreadX);
3716 /****************************************************************************
3717 Error replies to writebraw must have smb_wct == 1. Fix this up.
3718 ****************************************************************************/
3720 void error_to_writebrawerr(struct smb_request *req)
3722 uint8 *old_outbuf = req->outbuf;
3724 reply_outbuf(req, 1, 0);
3726 memcpy(req->outbuf, old_outbuf, smb_size);
3727 TALLOC_FREE(old_outbuf);
3730 /****************************************************************************
3731 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3732 ****************************************************************************/
3734 void reply_writebraw(struct smb_request *req)
3736 connection_struct *conn = req->conn;
3739 ssize_t total_written=0;
3740 size_t numtowrite=0;
3746 struct lock_struct lock;
3749 START_PROFILE(SMBwritebraw);
3752 * If we ever reply with an error, it must have the SMB command
3753 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3756 SCVAL(req->inbuf,smb_com,SMBwritec);
3758 if (srv_is_signing_active(smbd_server_conn)) {
3759 END_PROFILE(SMBwritebraw);
3760 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3761 "raw reads/writes are disallowed.");
3764 if (req->wct < 12) {
3765 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3766 error_to_writebrawerr(req);
3767 END_PROFILE(SMBwritebraw);
3771 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3772 if (!check_fsp(conn, req, fsp)) {
3773 error_to_writebrawerr(req);
3774 END_PROFILE(SMBwritebraw);
3778 if (!CHECK_WRITE(fsp)) {
3779 reply_doserror(req, ERRDOS, ERRbadaccess);
3780 error_to_writebrawerr(req);
3781 END_PROFILE(SMBwritebraw);
3785 tcount = IVAL(req->vwv+1, 0);
3786 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3787 write_through = BITSETW(req->vwv+7,0);
3789 /* We have to deal with slightly different formats depending
3790 on whether we are using the core+ or lanman1.0 protocol */
3792 if(Protocol <= PROTOCOL_COREPLUS) {
3793 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3794 data = smb_buf(req->inbuf);
3796 numtowrite = SVAL(req->vwv+10, 0);
3797 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3800 /* Ensure we don't write bytes past the end of this packet. */
3801 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3802 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3803 error_to_writebrawerr(req);
3804 END_PROFILE(SMBwritebraw);
3808 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3809 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3812 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3813 reply_doserror(req, ERRDOS, ERRlock);
3814 error_to_writebrawerr(req);
3815 END_PROFILE(SMBwritebraw);
3820 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3823 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3824 "wrote=%d sync=%d\n",
3825 fsp->fnum, (double)startpos, (int)numtowrite,
3826 (int)nwritten, (int)write_through));
3828 if (nwritten < (ssize_t)numtowrite) {
3829 reply_doserror(req, ERRHRD, ERRdiskfull);
3830 error_to_writebrawerr(req);
3834 total_written = nwritten;
3836 /* Allocate a buffer of 64k + length. */
3837 buf = TALLOC_ARRAY(NULL, char, 65540);
3839 reply_doserror(req, ERRDOS, ERRnomem);
3840 error_to_writebrawerr(req);
3844 /* Return a SMBwritebraw message to the redirector to tell
3845 * it to send more bytes */
3847 memcpy(buf, req->inbuf, smb_size);
3848 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3849 SCVAL(buf,smb_com,SMBwritebraw);
3850 SSVALS(buf,smb_vwv0,0xFFFF);
3852 if (!srv_send_smb(smbd_server_fd(),
3854 false, 0, /* no signing */
3855 IS_CONN_ENCRYPTED(conn),
3857 exit_server_cleanly("reply_writebraw: srv_send_smb "
3861 /* Now read the raw data into the buffer and write it */
3862 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3864 if (!NT_STATUS_IS_OK(status)) {
3865 exit_server_cleanly("secondary writebraw failed");
3868 /* Set up outbuf to return the correct size */
3869 reply_outbuf(req, 1, 0);
3871 if (numtowrite != 0) {
3873 if (numtowrite > 0xFFFF) {
3874 DEBUG(0,("reply_writebraw: Oversize secondary write "
3875 "raw requested (%u). Terminating\n",
3876 (unsigned int)numtowrite ));
3877 exit_server_cleanly("secondary writebraw failed");
3880 if (tcount > nwritten+numtowrite) {
3881 DEBUG(3,("reply_writebraw: Client overestimated the "
3883 (int)tcount,(int)nwritten,(int)numtowrite));
3886 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3888 if (!NT_STATUS_IS_OK(status)) {
3889 DEBUG(0,("reply_writebraw: Oversize secondary write "
3890 "raw read failed (%s). Terminating\n",
3891 nt_errstr(status)));
3892 exit_server_cleanly("secondary writebraw failed");
3895 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3896 if (nwritten == -1) {
3898 reply_nterror(req, map_nt_error_from_unix(errno));
3899 error_to_writebrawerr(req);
3903 if (nwritten < (ssize_t)numtowrite) {
3904 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3905 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3909 total_written += nwritten;
3914 SSVAL(req->outbuf,smb_vwv0,total_written);
3916 status = sync_file(conn, fsp, write_through);
3917 if (!NT_STATUS_IS_OK(status)) {
3918 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3919 fsp_str_dbg(fsp), nt_errstr(status)));
3920 reply_nterror(req, status);
3921 error_to_writebrawerr(req);
3925 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3927 fsp->fnum, (double)startpos, (int)numtowrite,
3928 (int)total_written));
3930 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3932 /* We won't return a status if write through is not selected - this
3933 * follows what WfWg does */
3934 END_PROFILE(SMBwritebraw);
3936 if (!write_through && total_written==tcount) {
3938 #if RABBIT_PELLET_FIX
3940 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3941 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3944 if (!send_keepalive(smbd_server_fd())) {
3945 exit_server_cleanly("reply_writebraw: send of "
3946 "keepalive failed");
3949 TALLOC_FREE(req->outbuf);
3954 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3956 END_PROFILE(SMBwritebraw);
3961 #define DBGC_CLASS DBGC_LOCKING
3963 /****************************************************************************
3964 Reply to a writeunlock (core+).
3965 ****************************************************************************/
3967 void reply_writeunlock(struct smb_request *req)
3969 connection_struct *conn = req->conn;
3970 ssize_t nwritten = -1;
3974 NTSTATUS status = NT_STATUS_OK;
3976 struct lock_struct lock;
3977 int saved_errno = 0;
3979 START_PROFILE(SMBwriteunlock);
3982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3983 END_PROFILE(SMBwriteunlock);
3987 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3989 if (!check_fsp(conn, req, fsp)) {
3990 END_PROFILE(SMBwriteunlock);
3994 if (!CHECK_WRITE(fsp)) {
3995 reply_doserror(req, ERRDOS,ERRbadaccess);
3996 END_PROFILE(SMBwriteunlock);
4000 numtowrite = SVAL(req->vwv+1, 0);
4001 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4002 data = (const char *)req->buf + 3;
4005 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4006 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4009 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4010 reply_doserror(req, ERRDOS, ERRlock);
4011 END_PROFILE(SMBwriteunlock);
4016 /* The special X/Open SMB protocol handling of
4017 zero length writes is *NOT* done for
4019 if(numtowrite == 0) {
4022 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4023 saved_errno = errno;
4026 status = sync_file(conn, fsp, False /* write through */);
4027 if (!NT_STATUS_IS_OK(status)) {
4028 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4029 fsp_str_dbg(fsp), nt_errstr(status)));
4030 reply_nterror(req, status);
4035 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4039 if((nwritten < numtowrite) && (numtowrite != 0)) {
4040 reply_doserror(req, ERRHRD, ERRdiskfull);
4045 status = do_unlock(smbd_messaging_context(),
4048 (uint64_t)numtowrite,
4052 if (NT_STATUS_V(status)) {
4053 reply_nterror(req, status);
4058 reply_outbuf(req, 1, 0);
4060 SSVAL(req->outbuf,smb_vwv0,nwritten);
4062 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4063 fsp->fnum, (int)numtowrite, (int)nwritten));
4067 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4070 END_PROFILE(SMBwriteunlock);
4075 #define DBGC_CLASS DBGC_ALL
4077 /****************************************************************************
4079 ****************************************************************************/
4081 void reply_write(struct smb_request *req)
4083 connection_struct *conn = req->conn;
4085 ssize_t nwritten = -1;
4089 struct lock_struct lock;
4091 int saved_errno = 0;
4093 START_PROFILE(SMBwrite);
4096 END_PROFILE(SMBwrite);
4097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4101 /* If it's an IPC, pass off the pipe handler. */
4103 reply_pipe_write(req);
4104 END_PROFILE(SMBwrite);
4108 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4110 if (!check_fsp(conn, req, fsp)) {
4111 END_PROFILE(SMBwrite);
4115 if (!CHECK_WRITE(fsp)) {
4116 reply_doserror(req, ERRDOS, ERRbadaccess);
4117 END_PROFILE(SMBwrite);
4121 numtowrite = SVAL(req->vwv+1, 0);
4122 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4123 data = (const char *)req->buf + 3;
4125 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4126 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4129 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4130 reply_doserror(req, ERRDOS, ERRlock);
4131 END_PROFILE(SMBwrite);
4136 * X/Open SMB protocol says that if smb_vwv1 is
4137 * zero then the file size should be extended or
4138 * truncated to the size given in smb_vwv[2-3].
4141 if(numtowrite == 0) {
4143 * This is actually an allocate call, and set EOF. JRA.
4145 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4147 reply_nterror(req, NT_STATUS_DISK_FULL);
4150 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4152 reply_nterror(req, NT_STATUS_DISK_FULL);
4155 trigger_write_time_update_immediate(fsp);
4157 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4160 status = sync_file(conn, fsp, False);
4161 if (!NT_STATUS_IS_OK(status)) {
4162 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4163 fsp_str_dbg(fsp), nt_errstr(status)));
4164 reply_nterror(req, status);
4169 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4173 if((nwritten == 0) && (numtowrite != 0)) {
4174 reply_doserror(req, ERRHRD, ERRdiskfull);
4178 reply_outbuf(req, 1, 0);
4180 SSVAL(req->outbuf,smb_vwv0,nwritten);
4182 if (nwritten < (ssize_t)numtowrite) {
4183 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4184 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4187 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4190 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4192 END_PROFILE(SMBwrite);
4196 /****************************************************************************
4197 Ensure a buffer is a valid writeX for recvfile purposes.
4198 ****************************************************************************/
4200 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4201 (2*14) + /* word count (including bcc) */ \
4204 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4207 connection_struct *conn = NULL;
4208 unsigned int doff = 0;
4209 size_t len = smb_len_large(inbuf);
4210 struct smbd_server_connection *sconn = smbd_server_conn;
4212 if (is_encrypted_packet(inbuf)) {
4213 /* Can't do this on encrypted
4218 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4222 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4223 CVAL(inbuf,smb_wct) != 14) {
4224 DEBUG(10,("is_valid_writeX_buffer: chained or "
4225 "invalid word length.\n"));
4229 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4231 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4235 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4238 if (IS_PRINT(conn)) {
4239 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4242 doff = SVAL(inbuf,smb_vwv11);
4244 numtowrite = SVAL(inbuf,smb_vwv10);
4246 if (len > doff && len - doff > 0xFFFF) {
4247 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4250 if (numtowrite == 0) {
4251 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4255 /* Ensure the sizes match up. */
4256 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4257 /* no pad byte...old smbclient :-( */
4258 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4260 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4264 if (len - doff != numtowrite) {
4265 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4266 "len = %u, doff = %u, numtowrite = %u\n",
4269 (unsigned int)numtowrite ));
4273 DEBUG(10,("is_valid_writeX_buffer: true "
4274 "len = %u, doff = %u, numtowrite = %u\n",
4277 (unsigned int)numtowrite ));
4282 /****************************************************************************
4283 Reply to a write and X.
4284 ****************************************************************************/
4286 void reply_write_and_X(struct smb_request *req)
4288 connection_struct *conn = req->conn;
4290 struct lock_struct lock;
4295 unsigned int smb_doff;
4296 unsigned int smblen;
4300 START_PROFILE(SMBwriteX);
4302 if ((req->wct != 12) && (req->wct != 14)) {
4303 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4304 END_PROFILE(SMBwriteX);
4308 numtowrite = SVAL(req->vwv+10, 0);
4309 smb_doff = SVAL(req->vwv+11, 0);
4310 smblen = smb_len(req->inbuf);
4312 if (req->unread_bytes > 0xFFFF ||
4313 (smblen > smb_doff &&
4314 smblen - smb_doff > 0xFFFF)) {
4315 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4318 if (req->unread_bytes) {
4319 /* Can't do a recvfile write on IPC$ */
4321 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4322 END_PROFILE(SMBwriteX);
4325 if (numtowrite != req->unread_bytes) {
4326 reply_doserror(req, ERRDOS, ERRbadmem);
4327 END_PROFILE(SMBwriteX);
4331 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4332 smb_doff + numtowrite > smblen) {
4333 reply_doserror(req, ERRDOS, ERRbadmem);
4334 END_PROFILE(SMBwriteX);
4339 /* If it's an IPC, pass off the pipe handler. */
4341 if (req->unread_bytes) {
4342 reply_doserror(req, ERRDOS, ERRbadmem);
4343 END_PROFILE(SMBwriteX);
4346 reply_pipe_write_and_X(req);
4347 END_PROFILE(SMBwriteX);
4351 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4352 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4353 write_through = BITSETW(req->vwv+7,0);
4355 if (!check_fsp(conn, req, fsp)) {
4356 END_PROFILE(SMBwriteX);
4360 if (!CHECK_WRITE(fsp)) {
4361 reply_doserror(req, ERRDOS, ERRbadaccess);
4362 END_PROFILE(SMBwriteX);
4366 data = smb_base(req->inbuf) + smb_doff;
4368 if(req->wct == 14) {
4369 #ifdef LARGE_SMB_OFF_T
4371 * This is a large offset (64 bit) write.
4373 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4375 #else /* !LARGE_SMB_OFF_T */
4378 * Ensure we haven't been sent a >32 bit offset.
4381 if(IVAL(req->vwv+12, 0) != 0) {
4382 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4383 "used and we don't support 64 bit offsets.\n",
4384 (unsigned int)IVAL(req->vwv+12, 0) ));
4385 reply_doserror(req, ERRDOS, ERRbadaccess);
4386 END_PROFILE(SMBwriteX);
4390 #endif /* LARGE_SMB_OFF_T */
4393 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4394 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4397 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4398 reply_doserror(req, ERRDOS, ERRlock);
4399 END_PROFILE(SMBwriteX);
4403 /* X/Open SMB protocol says that, unlike SMBwrite
4404 if the length is zero then NO truncation is
4405 done, just a write of zero. To truncate a file,
4408 if(numtowrite == 0) {
4412 if ((req->unread_bytes == 0) &&
4413 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4418 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4422 reply_nterror(req, map_nt_error_from_unix(errno));
4426 if((nwritten == 0) && (numtowrite != 0)) {
4427 reply_doserror(req, ERRHRD, ERRdiskfull);
4431 reply_outbuf(req, 6, 0);
4432 SSVAL(req->outbuf,smb_vwv2,nwritten);
4433 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4435 if (nwritten < (ssize_t)numtowrite) {
4436 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4437 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4440 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4441 fsp->fnum, (int)numtowrite, (int)nwritten));
4443 status = sync_file(conn, fsp, write_through);
4444 if (!NT_STATUS_IS_OK(status)) {
4445 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4446 fsp_str_dbg(fsp), nt_errstr(status)));
4447 reply_nterror(req, status);
4451 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4453 END_PROFILE(SMBwriteX);
4458 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4460 END_PROFILE(SMBwriteX);
4464 /****************************************************************************
4466 ****************************************************************************/
4468 void reply_lseek(struct smb_request *req)
4470 connection_struct *conn = req->conn;
4476 START_PROFILE(SMBlseek);
4479 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4480 END_PROFILE(SMBlseek);
4484 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4486 if (!check_fsp(conn, req, fsp)) {
4490 flush_write_cache(fsp, SEEK_FLUSH);
4492 mode = SVAL(req->vwv+1, 0) & 3;
4493 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4494 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4503 res = fsp->fh->pos + startpos;
4514 if (umode == SEEK_END) {
4515 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4516 if(errno == EINVAL) {
4517 SMB_OFF_T current_pos = startpos;
4518 SMB_STRUCT_STAT sbuf;
4520 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4522 map_nt_error_from_unix(errno));
4523 END_PROFILE(SMBlseek);
4527 current_pos += sbuf.st_ex_size;
4529 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4534 reply_nterror(req, map_nt_error_from_unix(errno));
4535 END_PROFILE(SMBlseek);
4542 reply_outbuf(req, 2, 0);
4543 SIVAL(req->outbuf,smb_vwv0,res);
4545 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4546 fsp->fnum, (double)startpos, (double)res, mode));
4548 END_PROFILE(SMBlseek);
4552 /****************************************************************************
4554 ****************************************************************************/
4556 void reply_flush(struct smb_request *req)
4558 connection_struct *conn = req->conn;
4562 START_PROFILE(SMBflush);
4565 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4569 fnum = SVAL(req->vwv+0, 0);
4570 fsp = file_fsp(req, fnum);
4572 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4577 file_sync_all(conn);
4579 NTSTATUS status = sync_file(conn, fsp, True);
4580 if (!NT_STATUS_IS_OK(status)) {
4581 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4582 fsp_str_dbg(fsp), nt_errstr(status)));
4583 reply_nterror(req, status);
4584 END_PROFILE(SMBflush);
4589 reply_outbuf(req, 0, 0);
4591 DEBUG(3,("flush\n"));
4592 END_PROFILE(SMBflush);
4596 /****************************************************************************
4598 conn POINTER CAN BE NULL HERE !
4599 ****************************************************************************/
4601 void reply_exit(struct smb_request *req)
4603 START_PROFILE(SMBexit);
4605 file_close_pid(req->smbpid, req->vuid);
4607 reply_outbuf(req, 0, 0);
4609 DEBUG(3,("exit\n"));
4611 END_PROFILE(SMBexit);
4615 /****************************************************************************
4616 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4617 ****************************************************************************/
4619 void reply_close(struct smb_request *req)
4621 connection_struct *conn = req->conn;
4622 NTSTATUS status = NT_STATUS_OK;
4623 files_struct *fsp = NULL;
4624 START_PROFILE(SMBclose);
4627 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4628 END_PROFILE(SMBclose);
4632 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4635 * We can only use check_fsp if we know it's not a directory.
4638 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4639 reply_doserror(req, ERRDOS, ERRbadfid);
4640 END_PROFILE(SMBclose);
4644 if(fsp->is_directory) {
4646 * Special case - close NT SMB directory handle.
4648 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4649 status = close_file(req, fsp, NORMAL_CLOSE);
4653 * Close ordinary file.
4656 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4657 fsp->fh->fd, fsp->fnum,
4658 conn->num_files_open));
4661 * Take care of any time sent in the close.
4664 t = srv_make_unix_date3(req->vwv+1);
4665 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4668 * close_file() returns the unix errno if an error
4669 * was detected on close - normally this is due to
4670 * a disk full error. If not then it was probably an I/O error.
4673 status = close_file(req, fsp, NORMAL_CLOSE);
4676 if (!NT_STATUS_IS_OK(status)) {
4677 reply_nterror(req, status);
4678 END_PROFILE(SMBclose);
4682 reply_outbuf(req, 0, 0);
4683 END_PROFILE(SMBclose);
4687 /****************************************************************************
4688 Reply to a writeclose (Core+ protocol).
4689 ****************************************************************************/
4691 void reply_writeclose(struct smb_request *req)
4693 connection_struct *conn = req->conn;
4695 ssize_t nwritten = -1;
4696 NTSTATUS close_status = NT_STATUS_OK;
4699 struct timespec mtime;
4701 struct lock_struct lock;
4703 START_PROFILE(SMBwriteclose);
4706 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4707 END_PROFILE(SMBwriteclose);
4711 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4713 if (!check_fsp(conn, req, fsp)) {
4714 END_PROFILE(SMBwriteclose);
4717 if (!CHECK_WRITE(fsp)) {
4718 reply_doserror(req, ERRDOS,ERRbadaccess);
4719 END_PROFILE(SMBwriteclose);
4723 numtowrite = SVAL(req->vwv+1, 0);
4724 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4725 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4726 data = (const char *)req->buf + 1;
4729 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4730 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4733 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4734 reply_doserror(req, ERRDOS,ERRlock);
4735 END_PROFILE(SMBwriteclose);
4740 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4742 set_close_write_time(fsp, mtime);
4745 * More insanity. W2K only closes the file if writelen > 0.
4750 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4751 "file %s\n", fsp_str_dbg(fsp)));
4752 close_status = close_file(req, fsp, NORMAL_CLOSE);
4755 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4756 fsp->fnum, (int)numtowrite, (int)nwritten,
4757 conn->num_files_open));
4759 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4760 reply_doserror(req, ERRHRD, ERRdiskfull);
4764 if(!NT_STATUS_IS_OK(close_status)) {
4765 reply_nterror(req, close_status);
4769 reply_outbuf(req, 1, 0);
4771 SSVAL(req->outbuf,smb_vwv0,nwritten);
4775 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4778 END_PROFILE(SMBwriteclose);
4783 #define DBGC_CLASS DBGC_LOCKING
4785 /****************************************************************************
4787 ****************************************************************************/
4789 void reply_lock(struct smb_request *req)
4791 connection_struct *conn = req->conn;
4792 uint64_t count,offset;
4795 struct byte_range_lock *br_lck = NULL;
4797 START_PROFILE(SMBlock);
4800 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4801 END_PROFILE(SMBlock);
4805 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4807 if (!check_fsp(conn, req, fsp)) {
4808 END_PROFILE(SMBlock);
4812 count = (uint64_t)IVAL(req->vwv+1, 0);
4813 offset = (uint64_t)IVAL(req->vwv+3, 0);
4815 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4816 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4818 br_lck = do_lock(smbd_messaging_context(),
4825 False, /* Non-blocking lock. */
4830 TALLOC_FREE(br_lck);
4832 if (NT_STATUS_V(status)) {
4833 reply_nterror(req, status);
4834 END_PROFILE(SMBlock);
4838 reply_outbuf(req, 0, 0);
4840 END_PROFILE(SMBlock);
4844 /****************************************************************************
4846 ****************************************************************************/
4848 void reply_unlock(struct smb_request *req)
4850 connection_struct *conn = req->conn;
4851 uint64_t count,offset;
4855 START_PROFILE(SMBunlock);
4858 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4859 END_PROFILE(SMBunlock);
4863 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4865 if (!check_fsp(conn, req, fsp)) {
4866 END_PROFILE(SMBunlock);
4870 count = (uint64_t)IVAL(req->vwv+1, 0);
4871 offset = (uint64_t)IVAL(req->vwv+3, 0);
4873 status = do_unlock(smbd_messaging_context(),
4880 if (NT_STATUS_V(status)) {
4881 reply_nterror(req, status);
4882 END_PROFILE(SMBunlock);
4886 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4887 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4889 reply_outbuf(req, 0, 0);
4891 END_PROFILE(SMBunlock);
4896 #define DBGC_CLASS DBGC_ALL
4898 /****************************************************************************
4900 conn POINTER CAN BE NULL HERE !
4901 ****************************************************************************/
4903 void reply_tdis(struct smb_request *req)
4905 struct smbd_server_connection *sconn = smbd_server_conn;
4906 connection_struct *conn = req->conn;
4907 START_PROFILE(SMBtdis);
4910 DEBUG(4,("Invalid connection in tdis\n"));
4911 reply_doserror(req, ERRSRV, ERRinvnid);
4912 END_PROFILE(SMBtdis);
4918 close_cnum(sconn, conn,req->vuid);
4921 reply_outbuf(req, 0, 0);
4922 END_PROFILE(SMBtdis);
4926 /****************************************************************************
4928 conn POINTER CAN BE NULL HERE !
4929 ****************************************************************************/
4931 void reply_echo(struct smb_request *req)
4933 connection_struct *conn = req->conn;
4934 struct smb_perfcount_data local_pcd;
4935 struct smb_perfcount_data *cur_pcd;
4939 START_PROFILE(SMBecho);
4941 smb_init_perfcount_data(&local_pcd);
4944 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4945 END_PROFILE(SMBecho);
4949 smb_reverb = SVAL(req->vwv+0, 0);
4951 reply_outbuf(req, 1, req->buflen);
4953 /* copy any incoming data back out */
4954 if (req->buflen > 0) {
4955 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4958 if (smb_reverb > 100) {
4959 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4963 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4965 /* this makes sure we catch the request pcd */
4966 if (seq_num == smb_reverb) {
4967 cur_pcd = &req->pcd;
4969 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4970 cur_pcd = &local_pcd;
4973 SSVAL(req->outbuf,smb_vwv0,seq_num);
4975 show_msg((char *)req->outbuf);
4976 if (!srv_send_smb(smbd_server_fd(),
4977 (char *)req->outbuf,
4978 true, req->seqnum+1,
4979 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4981 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4984 DEBUG(3,("echo %d times\n", smb_reverb));
4986 TALLOC_FREE(req->outbuf);
4988 END_PROFILE(SMBecho);
4992 /****************************************************************************
4993 Reply to a printopen.
4994 ****************************************************************************/
4996 void reply_printopen(struct smb_request *req)
4998 connection_struct *conn = req->conn;
5000 SMB_STRUCT_STAT sbuf;
5003 START_PROFILE(SMBsplopen);
5006 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5007 END_PROFILE(SMBsplopen);
5011 if (!CAN_PRINT(conn)) {
5012 reply_doserror(req, ERRDOS, ERRnoaccess);
5013 END_PROFILE(SMBsplopen);
5017 status = file_new(req, conn, &fsp);
5018 if(!NT_STATUS_IS_OK(status)) {
5019 reply_nterror(req, status);
5020 END_PROFILE(SMBsplopen);
5024 /* Open for exclusive use, write only. */
5025 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
5027 if (!NT_STATUS_IS_OK(status)) {
5028 file_free(req, fsp);
5029 reply_nterror(req, status);
5030 END_PROFILE(SMBsplopen);
5034 reply_outbuf(req, 1, 0);
5035 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5037 DEBUG(3,("openprint fd=%d fnum=%d\n",
5038 fsp->fh->fd, fsp->fnum));
5040 END_PROFILE(SMBsplopen);
5044 /****************************************************************************
5045 Reply to a printclose.
5046 ****************************************************************************/
5048 void reply_printclose(struct smb_request *req)
5050 connection_struct *conn = req->conn;
5054 START_PROFILE(SMBsplclose);
5057 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5058 END_PROFILE(SMBsplclose);
5062 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5064 if (!check_fsp(conn, req, fsp)) {
5065 END_PROFILE(SMBsplclose);
5069 if (!CAN_PRINT(conn)) {
5070 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
5071 END_PROFILE(SMBsplclose);
5075 DEBUG(3,("printclose fd=%d fnum=%d\n",
5076 fsp->fh->fd,fsp->fnum));
5078 status = close_file(req, fsp, NORMAL_CLOSE);
5080 if(!NT_STATUS_IS_OK(status)) {
5081 reply_nterror(req, status);
5082 END_PROFILE(SMBsplclose);
5086 reply_outbuf(req, 0, 0);
5088 END_PROFILE(SMBsplclose);
5092 /****************************************************************************
5093 Reply to a printqueue.
5094 ****************************************************************************/
5096 void reply_printqueue(struct smb_request *req)
5098 connection_struct *conn = req->conn;
5102 START_PROFILE(SMBsplretq);
5105 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5106 END_PROFILE(SMBsplretq);
5110 max_count = SVAL(req->vwv+0, 0);
5111 start_index = SVAL(req->vwv+1, 0);
5113 /* we used to allow the client to get the cnum wrong, but that
5114 is really quite gross and only worked when there was only
5115 one printer - I think we should now only accept it if they
5116 get it right (tridge) */
5117 if (!CAN_PRINT(conn)) {
5118 reply_doserror(req, ERRDOS, ERRnoaccess);
5119 END_PROFILE(SMBsplretq);
5123 reply_outbuf(req, 2, 3);
5124 SSVAL(req->outbuf,smb_vwv0,0);
5125 SSVAL(req->outbuf,smb_vwv1,0);
5126 SCVAL(smb_buf(req->outbuf),0,1);
5127 SSVAL(smb_buf(req->outbuf),1,0);
5129 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5130 start_index, max_count));
5133 print_queue_struct *queue = NULL;
5134 print_status_struct status;
5135 int count = print_queue_status(SNUM(conn), &queue, &status);
5136 int num_to_get = ABS(max_count);
5137 int first = (max_count>0?start_index:start_index+max_count+1);
5143 num_to_get = MIN(num_to_get,count-first);
5146 for (i=first;i<first+num_to_get;i++) {
5150 srv_put_dos_date2(p,0,queue[i].time);
5151 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5152 SSVAL(p,5, queue[i].job);
5153 SIVAL(p,7,queue[i].size);
5155 srvstr_push(blob, req->flags2, p+12,
5156 queue[i].fs_user, 16, STR_ASCII);
5158 if (message_push_blob(
5161 blob, sizeof(blob))) == -1) {
5162 reply_nterror(req, NT_STATUS_NO_MEMORY);
5163 END_PROFILE(SMBsplretq);
5169 SSVAL(req->outbuf,smb_vwv0,count);
5170 SSVAL(req->outbuf,smb_vwv1,
5171 (max_count>0?first+count:first-1));
5172 SCVAL(smb_buf(req->outbuf),0,1);
5173 SSVAL(smb_buf(req->outbuf),1,28*count);
5178 DEBUG(3,("%d entries returned in queue\n",count));
5181 END_PROFILE(SMBsplretq);
5185 /****************************************************************************
5186 Reply to a printwrite.
5187 ****************************************************************************/
5189 void reply_printwrite(struct smb_request *req)
5191 connection_struct *conn = req->conn;
5196 START_PROFILE(SMBsplwr);
5199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5200 END_PROFILE(SMBsplwr);
5204 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5206 if (!check_fsp(conn, req, fsp)) {
5207 END_PROFILE(SMBsplwr);
5211 if (!CAN_PRINT(conn)) {
5212 reply_doserror(req, ERRDOS, ERRnoaccess);
5213 END_PROFILE(SMBsplwr);
5217 if (!CHECK_WRITE(fsp)) {
5218 reply_doserror(req, ERRDOS, ERRbadaccess);
5219 END_PROFILE(SMBsplwr);
5223 numtowrite = SVAL(req->buf, 1);
5225 if (req->buflen < numtowrite + 3) {
5226 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5227 END_PROFILE(SMBsplwr);
5231 data = (const char *)req->buf + 3;
5233 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5234 reply_nterror(req, map_nt_error_from_unix(errno));
5235 END_PROFILE(SMBsplwr);
5239 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5241 END_PROFILE(SMBsplwr);
5245 /****************************************************************************
5247 ****************************************************************************/
5249 void reply_mkdir(struct smb_request *req)
5251 connection_struct *conn = req->conn;
5252 struct smb_filename *smb_dname = NULL;
5253 char *directory = NULL;
5255 TALLOC_CTX *ctx = talloc_tos();
5257 START_PROFILE(SMBmkdir);
5259 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5260 STR_TERMINATE, &status);
5261 if (!NT_STATUS_IS_OK(status)) {
5262 reply_nterror(req, status);
5266 status = filename_convert(ctx, conn,
5267 req->flags2 & FLAGS2_DFS_PATHNAMES,
5271 if (!NT_STATUS_IS_OK(status)) {
5272 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5273 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5274 ERRSRV, ERRbadpath);
5277 reply_nterror(req, status);
5281 status = create_directory(conn, req, smb_dname);
5283 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5285 if (!NT_STATUS_IS_OK(status)) {
5287 if (!use_nt_status()
5288 && NT_STATUS_EQUAL(status,
5289 NT_STATUS_OBJECT_NAME_COLLISION)) {
5291 * Yes, in the DOS error code case we get a
5292 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5293 * samba4 torture test.
5295 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5298 reply_nterror(req, status);
5302 reply_outbuf(req, 0, 0);
5304 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5306 TALLOC_FREE(smb_dname);
5307 END_PROFILE(SMBmkdir);
5311 /****************************************************************************
5312 Static function used by reply_rmdir to delete an entire directory
5313 tree recursively. Return True on ok, False on fail.
5314 ****************************************************************************/
5316 static bool recursive_rmdir(TALLOC_CTX *ctx,
5317 connection_struct *conn,
5318 struct smb_filename *smb_dname)
5320 const char *dname = NULL;
5324 struct smb_Dir *dir_hnd;
5326 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5328 dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0);
5332 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5333 struct smb_filename *smb_dname_full = NULL;
5334 char *fullname = NULL;
5335 bool do_break = true;
5338 if (ISDOT(dname) || ISDOTDOT(dname)) {
5342 if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
5347 /* Construct the full name. */
5348 fullname = talloc_asprintf(ctx,
5350 smb_dname->base_name,
5357 status = create_synthetic_smb_fname(talloc_tos(), fullname,
5360 if (!NT_STATUS_IS_OK(status)) {
5364 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5368 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5369 if(!recursive_rmdir(ctx, conn, smb_dname_full)) {
5372 if(SMB_VFS_RMDIR(conn,
5373 smb_dname_full->base_name) != 0) {
5376 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5380 /* Successful iteration. */
5384 TALLOC_FREE(smb_dname_full);
5385 TALLOC_FREE(fullname);
5391 TALLOC_FREE(dir_hnd);
5395 /****************************************************************************
5396 The internals of the rmdir code - called elsewhere.
5397 ****************************************************************************/
5399 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5400 connection_struct *conn,
5401 struct smb_filename *smb_dname)
5406 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5408 /* Might be a symlink. */
5409 if(SMB_VFS_LSTAT(conn, smb_dname) != 0) {
5410 return map_nt_error_from_unix(errno);
5413 if (S_ISLNK(smb_dname->st.st_ex_mode)) {
5414 /* Is what it points to a directory ? */
5415 if(SMB_VFS_STAT(conn, smb_dname) != 0) {
5416 return map_nt_error_from_unix(errno);
5418 if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
5419 return NT_STATUS_NOT_A_DIRECTORY;
5421 ret = SMB_VFS_UNLINK(conn, smb_dname);
5423 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5426 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5427 FILE_NOTIFY_CHANGE_DIR_NAME,
5428 smb_dname->base_name);
5429 return NT_STATUS_OK;
5432 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5434 * Check to see if the only thing in this directory are
5435 * vetoed files/directories. If so then delete them and
5436 * retry. If we fail to delete any of them (and we *don't*
5437 * do a recursive delete) then fail the rmdir.
5441 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5442 smb_dname->base_name, NULL,
5445 if(dir_hnd == NULL) {
5450 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5451 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5453 if (!is_visible_file(conn, smb_dname->base_name, dname,
5456 if(!IS_VETO_PATH(conn, dname)) {
5457 TALLOC_FREE(dir_hnd);
5463 /* We only have veto files/directories.
5464 * Are we allowed to delete them ? */
5466 if(!lp_recursive_veto_delete(SNUM(conn))) {
5467 TALLOC_FREE(dir_hnd);
5472 /* Do a recursive delete. */
5473 RewindDir(dir_hnd,&dirpos);
5474 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5475 struct smb_filename *smb_dname_full = NULL;
5476 char *fullname = NULL;
5477 bool do_break = true;
5480 if (ISDOT(dname) || ISDOTDOT(dname)) {
5483 if (!is_visible_file(conn, smb_dname->base_name, dname,
5488 fullname = talloc_asprintf(ctx,
5490 smb_dname->base_name,
5498 status = create_synthetic_smb_fname(talloc_tos(),
5502 if (!NT_STATUS_IS_OK(status)) {
5503 errno = map_errno_from_nt_status(status);
5507 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5510 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5511 if(!recursive_rmdir(ctx, conn,
5515 if(SMB_VFS_RMDIR(conn,
5516 smb_dname_full->base_name) != 0) {
5519 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5523 /* Successful iteration. */
5527 TALLOC_FREE(fullname);
5528 TALLOC_FREE(smb_dname_full);
5532 TALLOC_FREE(dir_hnd);
5533 /* Retry the rmdir */
5534 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5540 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5541 "%s\n", smb_fname_str_dbg(smb_dname),
5543 return map_nt_error_from_unix(errno);
5546 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5547 FILE_NOTIFY_CHANGE_DIR_NAME,
5548 smb_dname->base_name);
5550 return NT_STATUS_OK;
5553 /****************************************************************************
5555 ****************************************************************************/
5557 void reply_rmdir(struct smb_request *req)
5559 connection_struct *conn = req->conn;
5560 struct smb_filename *smb_dname = NULL;
5561 char *directory = NULL;
5563 TALLOC_CTX *ctx = talloc_tos();
5565 START_PROFILE(SMBrmdir);
5567 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5568 STR_TERMINATE, &status);
5569 if (!NT_STATUS_IS_OK(status)) {
5570 reply_nterror(req, status);
5574 status = filename_convert(ctx, conn,
5575 req->flags2 & FLAGS2_DFS_PATHNAMES,
5579 if (!NT_STATUS_IS_OK(status)) {
5580 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5581 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5582 ERRSRV, ERRbadpath);
5585 reply_nterror(req, status);
5589 if (is_ntfs_stream_smb_fname(smb_dname)) {
5590 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5594 dptr_closepath(smb_dname->base_name, req->smbpid);
5595 status = rmdir_internals(ctx, conn, smb_dname);
5596 if (!NT_STATUS_IS_OK(status)) {
5597 reply_nterror(req, status);
5601 reply_outbuf(req, 0, 0);
5603 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5605 TALLOC_FREE(smb_dname);
5606 END_PROFILE(SMBrmdir);
5610 /*******************************************************************
5611 Resolve wildcards in a filename rename.
5612 ********************************************************************/
5614 static bool resolve_wildcards(TALLOC_CTX *ctx,
5619 char *name2_copy = NULL;
5624 char *p,*p2, *pname1, *pname2;
5626 name2_copy = talloc_strdup(ctx, name2);
5631 pname1 = strrchr_m(name1,'/');
5632 pname2 = strrchr_m(name2_copy,'/');
5634 if (!pname1 || !pname2) {
5638 /* Truncate the copy of name2 at the last '/' */
5641 /* Now go past the '/' */
5645 root1 = talloc_strdup(ctx, pname1);
5646 root2 = talloc_strdup(ctx, pname2);
5648 if (!root1 || !root2) {
5652 p = strrchr_m(root1,'.');
5655 ext1 = talloc_strdup(ctx, p+1);
5657 ext1 = talloc_strdup(ctx, "");
5659 p = strrchr_m(root2,'.');
5662 ext2 = talloc_strdup(ctx, p+1);
5664 ext2 = talloc_strdup(ctx, "");
5667 if (!ext1 || !ext2) {
5675 /* Hmmm. Should this be mb-aware ? */
5678 } else if (*p2 == '*') {
5680 root2 = talloc_asprintf(ctx, "%s%s",
5699 /* Hmmm. Should this be mb-aware ? */
5702 } else if (*p2 == '*') {
5704 ext2 = talloc_asprintf(ctx, "%s%s",
5720 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5725 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5737 /****************************************************************************
5738 Ensure open files have their names updated. Updated to notify other smbd's
5740 ****************************************************************************/
5742 static void rename_open_files(connection_struct *conn,
5743 struct share_mode_lock *lck,
5744 const struct smb_filename *smb_fname_dst)
5747 bool did_rename = False;
5750 for(fsp = file_find_di_first(lck->id); fsp;
5751 fsp = file_find_di_next(fsp)) {
5752 /* fsp_name is a relative path under the fsp. To change this for other
5753 sharepaths we need to manipulate relative paths. */
5754 /* TODO - create the absolute path and manipulate the newname
5755 relative to the sharepath. */
5756 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5759 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5760 "(file_id %s) from %s -> %s\n", fsp->fnum,
5761 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5762 smb_fname_str_dbg(smb_fname_dst)));
5764 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5765 if (NT_STATUS_IS_OK(status)) {
5771 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5772 "for %s\n", file_id_string_tos(&lck->id),
5773 smb_fname_str_dbg(smb_fname_dst)));
5776 /* Send messages to all smbd's (not ourself) that the name has changed. */
5777 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5782 /****************************************************************************
5783 We need to check if the source path is a parent directory of the destination
5784 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5785 refuse the rename with a sharing violation. Under UNIX the above call can
5786 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5787 probably need to check that the client is a Windows one before disallowing
5788 this as a UNIX client (one with UNIX extensions) can know the source is a
5789 symlink and make this decision intelligently. Found by an excellent bug
5790 report from <AndyLiebman@aol.com>.
5791 ****************************************************************************/
5793 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5794 const struct smb_filename *smb_fname_dst)
5796 const char *psrc = smb_fname_src->base_name;
5797 const char *pdst = smb_fname_dst->base_name;
5800 if (psrc[0] == '.' && psrc[1] == '/') {
5803 if (pdst[0] == '.' && pdst[1] == '/') {
5806 if ((slen = strlen(psrc)) > strlen(pdst)) {
5809 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5813 * Do the notify calls from a rename
5816 static void notify_rename(connection_struct *conn, bool is_dir,
5817 const struct smb_filename *smb_fname_src,
5818 const struct smb_filename *smb_fname_dst)
5820 char *parent_dir_src = NULL;
5821 char *parent_dir_dst = NULL;
5822 char *fname_src = NULL;
5823 char *fname_dst = NULL;
5827 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5828 : FILE_NOTIFY_CHANGE_FILE_NAME;
5830 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5831 &parent_dir_src, NULL) ||
5832 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5833 &parent_dir_dst, NULL)) {
5837 status = get_full_smb_filename(talloc_tos(), smb_fname_src,
5839 if (!NT_STATUS_IS_OK(status)) {
5842 status = get_full_smb_filename(talloc_tos(), smb_fname_dst,
5844 if (!NT_STATUS_IS_OK(status)) {
5848 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5849 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, fname_src);
5850 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, fname_dst);
5853 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, fname_src);
5854 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, fname_dst);
5857 /* this is a strange one. w2k3 gives an additional event for
5858 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5859 files, but not directories */
5861 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5862 FILE_NOTIFY_CHANGE_ATTRIBUTES
5863 |FILE_NOTIFY_CHANGE_CREATION,
5867 TALLOC_FREE(parent_dir_src);
5868 TALLOC_FREE(parent_dir_dst);
5869 TALLOC_FREE(fname_src);
5870 TALLOC_FREE(fname_dst);
5873 /****************************************************************************
5874 Rename an open file - given an fsp.
5875 ****************************************************************************/
5877 NTSTATUS rename_internals_fsp(connection_struct *conn,
5879 const struct smb_filename *smb_fname_dst_in,
5881 bool replace_if_exists)
5883 TALLOC_CTX *ctx = talloc_tos();
5884 struct smb_filename *smb_fname_src = NULL;
5885 struct smb_filename *smb_fname_dst = NULL;
5886 SMB_STRUCT_STAT sbuf;
5887 NTSTATUS status = NT_STATUS_OK;
5888 struct share_mode_lock *lck = NULL;
5889 bool dst_exists, old_is_stream, new_is_stream;
5893 status = check_name(conn, smb_fname_dst_in->base_name);
5894 if (!NT_STATUS_IS_OK(status)) {
5898 /* Make a copy of the src and dst smb_fname structs */
5899 status = copy_smb_filename(ctx, fsp->fsp_name, &smb_fname_src);
5900 if (!NT_STATUS_IS_OK(status)) {
5904 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5905 if (!NT_STATUS_IS_OK(status)) {
5909 /* Ensure the dst smb_fname contains a '/' */
5910 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5912 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5913 smb_fname_dst->base_name);
5915 status = NT_STATUS_NO_MEMORY;
5918 TALLOC_FREE(smb_fname_dst->base_name);
5919 smb_fname_dst->base_name = tmp;
5923 * Check for special case with case preserving and not
5924 * case sensitive. If the old last component differs from the original
5925 * last component only by case, then we should allow
5926 * the rename (user is trying to change the case of the
5929 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5930 strequal(smb_fname_src->base_name, smb_fname_dst->base_name) &&
5931 strequal(smb_fname_src->stream_name, smb_fname_dst->stream_name)) {
5933 char *fname_dst_lcomp_base_mod = NULL;
5934 struct smb_filename *smb_fname_orig_lcomp = NULL;
5937 * Get the last component of the destination name. Note that
5938 * we guarantee that destination name contains a '/' character
5941 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5942 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5943 if (!fname_dst_lcomp_base_mod) {
5944 status = NT_STATUS_NO_MEMORY;
5949 * Create an smb_filename struct using the original last
5950 * component of the destination.
5952 status = create_synthetic_smb_fname_split(ctx,
5953 smb_fname_dst->original_lcomp, NULL,
5954 &smb_fname_orig_lcomp);
5955 if (!NT_STATUS_IS_OK(status)) {
5956 TALLOC_FREE(fname_dst_lcomp_base_mod);
5960 /* If the base names only differ by case, use original. */
5961 if(!strcsequal(fname_dst_lcomp_base_mod,
5962 smb_fname_orig_lcomp->base_name)) {
5965 * Replace the modified last component with the
5968 *last_slash = '\0'; /* Truncate at the '/' */
5969 tmp = talloc_asprintf(smb_fname_dst,
5971 smb_fname_dst->base_name,
5972 smb_fname_orig_lcomp->base_name);
5974 status = NT_STATUS_NO_MEMORY;
5975 TALLOC_FREE(fname_dst_lcomp_base_mod);
5976 TALLOC_FREE(smb_fname_orig_lcomp);
5979 TALLOC_FREE(smb_fname_dst->base_name);
5980 smb_fname_dst->base_name = tmp;
5983 /* If the stream_names only differ by case, use original. */
5984 if(!strcsequal(smb_fname_dst->stream_name,
5985 smb_fname_orig_lcomp->stream_name)) {
5987 /* Use the original stream. */
5988 tmp = talloc_strdup(smb_fname_dst,
5989 smb_fname_orig_lcomp->stream_name);
5991 status = NT_STATUS_NO_MEMORY;
5992 TALLOC_FREE(fname_dst_lcomp_base_mod);
5993 TALLOC_FREE(smb_fname_orig_lcomp);
5996 TALLOC_FREE(smb_fname_dst->stream_name);
5997 smb_fname_dst->stream_name = tmp;
5999 TALLOC_FREE(fname_dst_lcomp_base_mod);
6000 TALLOC_FREE(smb_fname_orig_lcomp);
6004 * If the src and dest names are identical - including case,
6005 * don't do the rename, just return success.
6008 if (strcsequal(smb_fname_src->base_name, smb_fname_dst->base_name) &&
6009 strcsequal(smb_fname_src->stream_name,
6010 smb_fname_dst->stream_name)) {
6011 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6012 "- returning success\n",
6013 smb_fname_str_dbg(smb_fname_dst)));
6014 status = NT_STATUS_OK;
6018 old_is_stream = is_ntfs_stream_smb_fname(smb_fname_src);
6019 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6021 /* Return the correct error code if both names aren't streams. */
6022 if (!old_is_stream && new_is_stream) {
6023 status = NT_STATUS_OBJECT_NAME_INVALID;
6027 if (old_is_stream && !new_is_stream) {
6028 status = NT_STATUS_INVALID_PARAMETER;
6032 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6034 if(!replace_if_exists && dst_exists) {
6035 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6036 "%s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6037 smb_fname_str_dbg(smb_fname_dst)));
6038 status = NT_STATUS_OBJECT_NAME_COLLISION;
6043 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6044 &smb_fname_dst->st);
6045 files_struct *dst_fsp = file_find_di_first(fileid);
6046 /* The file can be open when renaming a stream */
6047 if (dst_fsp && !new_is_stream) {
6048 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6049 status = NT_STATUS_ACCESS_DENIED;
6054 /* Ensure we have a valid stat struct for the source. */
6055 if (fsp->fh->fd != -1) {
6056 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
6057 status = map_nt_error_from_unix(errno);
6062 if (fsp->posix_open) {
6063 ret = SMB_VFS_LSTAT(conn, smb_fname_src);
6066 ret = SMB_VFS_STAT(conn, smb_fname_src);
6069 status = map_nt_error_from_unix(errno);
6072 sbuf = smb_fname_src->st;
6075 status = can_rename(conn, fsp, attrs, &sbuf);
6077 if (!NT_STATUS_IS_OK(status)) {
6078 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6079 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6080 smb_fname_str_dbg(smb_fname_dst)));
6081 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6082 status = NT_STATUS_ACCESS_DENIED;
6086 if (rename_path_prefix_equal(smb_fname_src, smb_fname_dst)) {
6087 status = NT_STATUS_ACCESS_DENIED;
6090 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6094 * We have the file open ourselves, so not being able to get the
6095 * corresponding share mode lock is a fatal error.
6098 SMB_ASSERT(lck != NULL);
6100 if(SMB_VFS_RENAME(conn, smb_fname_src, smb_fname_dst) == 0) {
6101 uint32 create_options = fsp->fh->private_options;
6103 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6104 "%s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6105 smb_fname_str_dbg(smb_fname_dst)));
6107 notify_rename(conn, fsp->is_directory, smb_fname_src,
6110 rename_open_files(conn, lck, smb_fname_dst);
6113 * A rename acts as a new file create w.r.t. allowing an initial delete
6114 * on close, probably because in Windows there is a new handle to the
6115 * new file. If initial delete on close was requested but not
6116 * originally set, we need to set it here. This is probably not 100% correct,
6117 * but will work for the CIFSFS client which in non-posix mode
6118 * depends on these semantics. JRA.
6121 if (create_options & FILE_DELETE_ON_CLOSE) {
6122 status = can_set_delete_on_close(fsp, True, 0);
6124 if (NT_STATUS_IS_OK(status)) {
6125 /* Note that here we set the *inital* delete on close flag,
6126 * not the regular one. The magic gets handled in close. */
6127 fsp->initial_delete_on_close = True;
6131 status = NT_STATUS_OK;
6137 if (errno == ENOTDIR || errno == EISDIR) {
6138 status = NT_STATUS_OBJECT_NAME_COLLISION;
6140 status = map_nt_error_from_unix(errno);
6143 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6144 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6145 smb_fname_str_dbg(smb_fname_dst)));
6148 TALLOC_FREE(smb_fname_src);
6149 TALLOC_FREE(smb_fname_dst);
6154 /****************************************************************************
6155 The guts of the rename command, split out so it may be called by the NT SMB
6157 ****************************************************************************/
6159 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6160 connection_struct *conn,
6161 struct smb_request *req,
6162 const char *name_in,
6163 const char *newname_in,
6165 bool replace_if_exists,
6168 uint32_t access_mask)
6170 struct smb_filename *smb_fname_src = NULL;
6171 struct smb_filename *smb_fname_dst = NULL;
6172 char *fname_src_dir = NULL;
6173 char *fname_src_mask = NULL;
6175 NTSTATUS status = NT_STATUS_OK;
6176 struct smb_Dir *dir_hnd = NULL;
6179 int create_options = 0;
6180 bool posix_pathnames = lp_posix_pathnames();
6182 status = unix_convert(ctx, conn, name_in, &smb_fname_src,
6183 src_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6184 if (!NT_STATUS_IS_OK(status)) {
6188 status = unix_convert(ctx, conn, newname_in, &smb_fname_dst,
6190 (dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0)));
6191 if (!NT_STATUS_IS_OK(status)) {
6196 * Split the old name into directory and last component
6197 * strings. Note that unix_convert may have stripped off a
6198 * leading ./ from both name and newname if the rename is
6199 * at the root of the share. We need to make sure either both
6200 * name and newname contain a / character or neither of them do
6201 * as this is checked in resolve_wildcards().
6204 /* Split up the directory from the filename/mask. */
6205 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6206 &fname_src_dir, &fname_src_mask);
6207 if (!NT_STATUS_IS_OK(status)) {
6208 status = NT_STATUS_NO_MEMORY;
6213 * We should only check the mangled cache
6214 * here if unix_convert failed. This means
6215 * that the path in 'mask' doesn't exist
6216 * on the file system and so we need to look
6217 * for a possible mangle. This patch from
6218 * Tine Smukavec <valentin.smukavec@hermes.si>.
6221 if (!VALID_STAT(smb_fname_src->st) &&
6222 mangle_is_mangled(fname_src_mask, conn->params)) {
6223 char *new_mask = NULL;
6224 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6227 TALLOC_FREE(fname_src_mask);
6228 fname_src_mask = new_mask;
6232 if (!src_has_wild) {
6236 * Only one file needs to be renamed. Append the mask back
6237 * onto the directory.
6239 TALLOC_FREE(smb_fname_src->base_name);
6240 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6244 if (!smb_fname_src->base_name) {
6245 status = NT_STATUS_NO_MEMORY;
6249 /* Ensure dst fname contains a '/' also */
6250 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6252 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6253 smb_fname_dst->base_name);
6255 status = NT_STATUS_NO_MEMORY;
6258 TALLOC_FREE(smb_fname_dst->base_name);
6259 smb_fname_dst->base_name = tmp;
6262 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6263 "case_preserve = %d, short case preserve = %d, "
6264 "directory = %s, newname = %s, "
6265 "last_component_dest = %s\n",
6266 conn->case_sensitive, conn->case_preserve,
6267 conn->short_case_preserve,
6268 smb_fname_str_dbg(smb_fname_src),
6269 smb_fname_str_dbg(smb_fname_dst),
6270 smb_fname_dst->original_lcomp));
6272 /* The dest name still may have wildcards. */
6273 if (dest_has_wild) {
6274 char *fname_dst_mod = NULL;
6275 if (!resolve_wildcards(smb_fname_dst,
6276 smb_fname_src->base_name,
6277 smb_fname_dst->base_name,
6279 DEBUG(6, ("rename_internals: resolve_wildcards "
6281 smb_fname_src->base_name,
6282 smb_fname_dst->base_name));
6283 status = NT_STATUS_NO_MEMORY;
6286 TALLOC_FREE(smb_fname_dst->base_name);
6287 smb_fname_dst->base_name = fname_dst_mod;
6290 ZERO_STRUCT(smb_fname_src->st);
6291 if (posix_pathnames) {
6292 SMB_VFS_LSTAT(conn, smb_fname_src);
6294 SMB_VFS_STAT(conn, smb_fname_src);
6297 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6298 create_options |= FILE_DIRECTORY_FILE;
6301 status = SMB_VFS_CREATE_FILE(
6304 0, /* root_dir_fid */
6305 smb_fname_src, /* fname */
6306 access_mask, /* access_mask */
6307 (FILE_SHARE_READ | /* share_access */
6309 FILE_OPEN, /* create_disposition*/
6310 create_options, /* create_options */
6311 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6312 0, /* oplock_request */
6313 0, /* allocation_size */
6319 if (!NT_STATUS_IS_OK(status)) {
6320 DEBUG(3, ("Could not open rename source %s: %s\n",
6321 smb_fname_str_dbg(smb_fname_src),
6322 nt_errstr(status)));
6326 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6327 attrs, replace_if_exists);
6329 close_file(req, fsp, NORMAL_CLOSE);
6331 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6332 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6333 smb_fname_str_dbg(smb_fname_dst)));
6339 * Wildcards - process each file that matches.
6341 if (strequal(fname_src_mask, "????????.???")) {
6342 TALLOC_FREE(fname_src_mask);
6343 fname_src_mask = talloc_strdup(ctx, "*");
6344 if (!fname_src_mask) {
6345 status = NT_STATUS_NO_MEMORY;
6350 status = check_name(conn, fname_src_dir);
6351 if (!NT_STATUS_IS_OK(status)) {
6355 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6357 if (dir_hnd == NULL) {
6358 status = map_nt_error_from_unix(errno);
6362 status = NT_STATUS_NO_SUCH_FILE;
6364 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6365 * - gentest fix. JRA
6368 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
6369 files_struct *fsp = NULL;
6370 char *destname = NULL;
6371 bool sysdir_entry = False;
6373 /* Quick check for "." and ".." */
6374 if (ISDOT(dname) || ISDOTDOT(dname)) {
6376 sysdir_entry = True;
6382 if (!is_visible_file(conn, fname_src_dir, dname,
6383 &smb_fname_src->st, false)) {
6387 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6392 status = NT_STATUS_OBJECT_NAME_INVALID;
6396 TALLOC_FREE(smb_fname_src->base_name);
6397 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6401 if (!smb_fname_src->base_name) {
6402 status = NT_STATUS_NO_MEMORY;
6406 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6407 smb_fname_dst->base_name,
6409 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6410 smb_fname_src->base_name, destname));
6414 status = NT_STATUS_NO_MEMORY;
6418 TALLOC_FREE(smb_fname_dst->base_name);
6419 smb_fname_dst->base_name = destname;
6421 ZERO_STRUCT(smb_fname_src->st);
6422 if (posix_pathnames) {
6423 SMB_VFS_LSTAT(conn, smb_fname_src);
6425 SMB_VFS_STAT(conn, smb_fname_src);
6430 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6431 create_options |= FILE_DIRECTORY_FILE;
6434 status = SMB_VFS_CREATE_FILE(
6437 0, /* root_dir_fid */
6438 smb_fname_src, /* fname */
6439 access_mask, /* access_mask */
6440 (FILE_SHARE_READ | /* share_access */
6442 FILE_OPEN, /* create_disposition*/
6443 create_options, /* create_options */
6444 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6445 0, /* oplock_request */
6446 0, /* allocation_size */
6452 if (!NT_STATUS_IS_OK(status)) {
6453 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6454 "returned %s rename %s -> %s\n",
6456 smb_fname_str_dbg(smb_fname_src),
6457 smb_fname_str_dbg(smb_fname_dst)));
6461 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6463 if (!smb_fname_dst->original_lcomp) {
6464 status = NT_STATUS_NO_MEMORY;
6468 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6469 attrs, replace_if_exists);
6471 close_file(req, fsp, NORMAL_CLOSE);
6473 if (!NT_STATUS_IS_OK(status)) {
6474 DEBUG(3, ("rename_internals_fsp returned %s for "
6475 "rename %s -> %s\n", nt_errstr(status),
6476 smb_fname_str_dbg(smb_fname_src),
6477 smb_fname_str_dbg(smb_fname_dst)));
6483 DEBUG(3,("rename_internals: doing rename on %s -> "
6484 "%s\n", smb_fname_str_dbg(smb_fname_src),
6485 smb_fname_str_dbg(smb_fname_src)));
6488 TALLOC_FREE(dir_hnd);
6490 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6491 status = map_nt_error_from_unix(errno);
6495 TALLOC_FREE(smb_fname_src);
6496 TALLOC_FREE(smb_fname_dst);
6497 TALLOC_FREE(fname_src_dir);
6498 TALLOC_FREE(fname_src_mask);
6502 /****************************************************************************
6504 ****************************************************************************/
6506 void reply_mv(struct smb_request *req)
6508 connection_struct *conn = req->conn;
6510 char *newname = NULL;
6514 bool src_has_wcard = False;
6515 bool dest_has_wcard = False;
6516 TALLOC_CTX *ctx = talloc_tos();
6518 START_PROFILE(SMBmv);
6521 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6526 attrs = SVAL(req->vwv+0, 0);
6528 p = (const char *)req->buf + 1;
6529 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6530 &status, &src_has_wcard);
6531 if (!NT_STATUS_IS_OK(status)) {
6532 reply_nterror(req, status);
6537 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6538 &status, &dest_has_wcard);
6539 if (!NT_STATUS_IS_OK(status)) {
6540 reply_nterror(req, status);
6545 status = resolve_dfspath_wcard(ctx, conn,
6546 req->flags2 & FLAGS2_DFS_PATHNAMES,
6550 if (!NT_STATUS_IS_OK(status)) {
6551 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6552 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6553 ERRSRV, ERRbadpath);
6557 reply_nterror(req, status);
6562 status = resolve_dfspath_wcard(ctx, conn,
6563 req->flags2 & FLAGS2_DFS_PATHNAMES,
6567 if (!NT_STATUS_IS_OK(status)) {
6568 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6569 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6570 ERRSRV, ERRbadpath);
6574 reply_nterror(req, status);
6579 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6581 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6582 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6583 if (!NT_STATUS_IS_OK(status)) {
6584 if (open_was_deferred(req->mid)) {
6585 /* We have re-scheduled this call. */
6589 reply_nterror(req, status);
6594 reply_outbuf(req, 0, 0);
6600 /*******************************************************************
6601 Copy a file as part of a reply_copy.
6602 ******************************************************************/
6605 * TODO: check error codes on all callers
6608 NTSTATUS copy_file(TALLOC_CTX *ctx,
6609 connection_struct *conn,
6610 struct smb_filename *smb_fname_src,
6611 struct smb_filename *smb_fname_dst,
6614 bool target_is_directory)
6616 struct smb_filename *smb_fname_dst_tmp = NULL;
6618 files_struct *fsp1,*fsp2;
6620 uint32 new_create_disposition;
6624 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6625 if (!NT_STATUS_IS_OK(status)) {
6630 * If the target is a directory, extract the last component from the
6631 * src filename and append it to the dst filename
6633 if (target_is_directory) {
6636 /* dest/target can't be a stream if it's a directory. */
6637 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6639 p = strrchr_m(smb_fname_src->base_name,'/');
6643 p = smb_fname_src->base_name;
6645 smb_fname_dst_tmp->base_name =
6646 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6648 if (!smb_fname_dst_tmp->base_name) {
6649 status = NT_STATUS_NO_MEMORY;
6654 status = vfs_file_exist(conn, smb_fname_src);
6655 if (!NT_STATUS_IS_OK(status)) {
6659 if (!target_is_directory && count) {
6660 new_create_disposition = FILE_OPEN;
6662 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6663 0, ofun, NULL, NULL,
6664 &new_create_disposition,
6666 status = NT_STATUS_INVALID_PARAMETER;
6671 /* Open the src file for reading. */
6672 status = SMB_VFS_CREATE_FILE(
6675 0, /* root_dir_fid */
6676 smb_fname_src, /* fname */
6677 FILE_GENERIC_READ, /* access_mask */
6678 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6679 FILE_OPEN, /* create_disposition*/
6680 0, /* create_options */
6681 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6682 INTERNAL_OPEN_ONLY, /* oplock_request */
6683 0, /* allocation_size */
6689 if (!NT_STATUS_IS_OK(status)) {
6693 dosattrs = dos_mode(conn, smb_fname_src);
6695 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6696 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6699 /* Open the dst file for writing. */
6700 status = SMB_VFS_CREATE_FILE(
6703 0, /* root_dir_fid */
6704 smb_fname_dst, /* fname */
6705 FILE_GENERIC_WRITE, /* access_mask */
6706 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6707 new_create_disposition, /* create_disposition*/
6708 0, /* create_options */
6709 dosattrs, /* file_attributes */
6710 INTERNAL_OPEN_ONLY, /* oplock_request */
6711 0, /* allocation_size */
6717 if (!NT_STATUS_IS_OK(status)) {
6718 close_file(NULL, fsp1, ERROR_CLOSE);
6722 if ((ofun&3) == 1) {
6723 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6724 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6726 * Stop the copy from occurring.
6729 smb_fname_src->st.st_ex_size = 0;
6733 /* Do the actual copy. */
6734 if (smb_fname_src->st.st_ex_size) {
6735 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6738 close_file(NULL, fsp1, NORMAL_CLOSE);
6740 /* Ensure the modtime is set correctly on the destination file. */
6741 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6744 * As we are opening fsp1 read-only we only expect
6745 * an error on close on fsp2 if we are out of space.
6746 * Thus we don't look at the error return from the
6749 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6751 if (!NT_STATUS_IS_OK(status)) {
6755 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6756 status = NT_STATUS_DISK_FULL;
6760 status = NT_STATUS_OK;
6763 TALLOC_FREE(smb_fname_dst_tmp);
6767 /****************************************************************************
6768 Reply to a file copy.
6769 ****************************************************************************/
6771 void reply_copy(struct smb_request *req)
6773 connection_struct *conn = req->conn;
6774 struct smb_filename *smb_fname_src = NULL;
6775 struct smb_filename *smb_fname_dst = NULL;
6776 char *fname_src = NULL;
6777 char *fname_dst = NULL;
6778 char *fname_src_mask = NULL;
6779 char *fname_src_dir = NULL;
6782 int error = ERRnoaccess;
6786 bool target_is_directory=False;
6787 bool source_has_wild = False;
6788 bool dest_has_wild = False;
6790 TALLOC_CTX *ctx = talloc_tos();
6792 START_PROFILE(SMBcopy);
6795 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6799 tid2 = SVAL(req->vwv+0, 0);
6800 ofun = SVAL(req->vwv+1, 0);
6801 flags = SVAL(req->vwv+2, 0);
6803 p = (const char *)req->buf;
6804 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6805 &status, &source_has_wild);
6806 if (!NT_STATUS_IS_OK(status)) {
6807 reply_nterror(req, status);
6810 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6811 &status, &dest_has_wild);
6812 if (!NT_STATUS_IS_OK(status)) {
6813 reply_nterror(req, status);
6817 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6819 if (tid2 != conn->cnum) {
6820 /* can't currently handle inter share copies XXXX */
6821 DEBUG(3,("Rejecting inter-share copy\n"));
6822 reply_doserror(req, ERRSRV, ERRinvdevice);
6826 status = resolve_dfspath_wcard(ctx, conn,
6827 req->flags2 & FLAGS2_DFS_PATHNAMES,
6831 if (!NT_STATUS_IS_OK(status)) {
6832 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6833 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6834 ERRSRV, ERRbadpath);
6837 reply_nterror(req, status);
6841 status = resolve_dfspath_wcard(ctx, conn,
6842 req->flags2 & FLAGS2_DFS_PATHNAMES,
6846 if (!NT_STATUS_IS_OK(status)) {
6847 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6848 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6849 ERRSRV, ERRbadpath);
6852 reply_nterror(req, status);
6856 status = unix_convert(ctx, conn, fname_src, &smb_fname_src,
6857 source_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6858 if (!NT_STATUS_IS_OK(status)) {
6859 reply_nterror(req, status);
6863 status = unix_convert(ctx, conn, fname_dst, &smb_fname_dst,
6864 dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6865 if (!NT_STATUS_IS_OK(status)) {
6866 reply_nterror(req, status);
6870 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6872 if ((flags&1) && target_is_directory) {
6873 reply_doserror(req, ERRDOS, ERRbadfile);
6877 if ((flags&2) && !target_is_directory) {
6878 reply_doserror(req, ERRDOS, ERRbadpath);
6882 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6883 /* wants a tree copy! XXXX */
6884 DEBUG(3,("Rejecting tree copy\n"));
6885 reply_doserror(req, ERRSRV, ERRerror);
6889 /* Split up the directory from the filename/mask. */
6890 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6891 &fname_src_dir, &fname_src_mask);
6892 if (!NT_STATUS_IS_OK(status)) {
6893 reply_nterror(req, NT_STATUS_NO_MEMORY);
6898 * We should only check the mangled cache
6899 * here if unix_convert failed. This means
6900 * that the path in 'mask' doesn't exist
6901 * on the file system and so we need to look
6902 * for a possible mangle. This patch from
6903 * Tine Smukavec <valentin.smukavec@hermes.si>.
6905 if (!VALID_STAT(smb_fname_src->st) &&
6906 mangle_is_mangled(fname_src_mask, conn->params)) {
6907 char *new_mask = NULL;
6908 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6909 &new_mask, conn->params);
6911 /* Use demangled name if one was successfully found. */
6913 TALLOC_FREE(fname_src_mask);
6914 fname_src_mask = new_mask;
6918 if (!source_has_wild) {
6921 * Only one file needs to be copied. Append the mask back onto
6924 TALLOC_FREE(smb_fname_src->base_name);
6925 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6929 if (!smb_fname_src->base_name) {
6930 reply_nterror(req, NT_STATUS_NO_MEMORY);
6934 if (dest_has_wild) {
6935 char *fname_dst_mod = NULL;
6936 if (!resolve_wildcards(smb_fname_dst,
6937 smb_fname_src->base_name,
6938 smb_fname_dst->base_name,
6940 reply_nterror(req, NT_STATUS_NO_MEMORY);
6943 TALLOC_FREE(smb_fname_dst->base_name);
6944 smb_fname_dst->base_name = fname_dst_mod;
6947 status = check_name(conn, smb_fname_src->base_name);
6948 if (!NT_STATUS_IS_OK(status)) {
6949 reply_nterror(req, status);
6953 status = check_name(conn, smb_fname_dst->base_name);
6954 if (!NT_STATUS_IS_OK(status)) {
6955 reply_nterror(req, status);
6959 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6960 ofun, count, target_is_directory);
6962 if(!NT_STATUS_IS_OK(status)) {
6963 reply_nterror(req, status);
6969 struct smb_Dir *dir_hnd = NULL;
6970 const char *dname = NULL;
6974 * There is a wildcard that requires us to actually read the
6975 * src dir and copy each file matching the mask to the dst.
6976 * Right now streams won't be copied, but this could
6977 * presumably be added with a nested loop for reach dir entry.
6979 SMB_ASSERT(!smb_fname_src->stream_name);
6980 SMB_ASSERT(!smb_fname_dst->stream_name);
6982 smb_fname_src->stream_name = NULL;
6983 smb_fname_dst->stream_name = NULL;
6985 if (strequal(fname_src_mask,"????????.???")) {
6986 TALLOC_FREE(fname_src_mask);
6987 fname_src_mask = talloc_strdup(ctx, "*");
6988 if (!fname_src_mask) {
6989 reply_nterror(req, NT_STATUS_NO_MEMORY);
6994 status = check_name(conn, fname_src_dir);
6995 if (!NT_STATUS_IS_OK(status)) {
6996 reply_nterror(req, status);
7000 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7001 if (dir_hnd == NULL) {
7002 status = map_nt_error_from_unix(errno);
7003 reply_nterror(req, status);
7009 /* Iterate over the src dir copying each entry to the dst. */
7010 while ((dname = ReadDirName(dir_hnd, &offset,
7011 &smb_fname_src->st))) {
7012 char *destname = NULL;
7014 if (ISDOT(dname) || ISDOTDOT(dname)) {
7018 if (!is_visible_file(conn, fname_src_dir, dname,
7019 &smb_fname_src->st, false)) {
7023 if(!mask_match(dname, fname_src_mask,
7024 conn->case_sensitive)) {
7028 error = ERRnoaccess;
7030 /* Get the src smb_fname struct setup. */
7031 TALLOC_FREE(smb_fname_src->base_name);
7032 smb_fname_src->base_name =
7033 talloc_asprintf(smb_fname_src, "%s/%s",
7034 fname_src_dir, dname);
7036 if (!smb_fname_src->base_name) {
7037 TALLOC_FREE(dir_hnd);
7038 reply_nterror(req, NT_STATUS_NO_MEMORY);
7042 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7043 smb_fname_dst->base_name,
7048 TALLOC_FREE(dir_hnd);
7049 reply_nterror(req, NT_STATUS_NO_MEMORY);
7053 TALLOC_FREE(smb_fname_dst->base_name);
7054 smb_fname_dst->base_name = destname;
7056 status = check_name(conn, smb_fname_src->base_name);
7057 if (!NT_STATUS_IS_OK(status)) {
7058 TALLOC_FREE(dir_hnd);
7059 reply_nterror(req, status);
7063 status = check_name(conn, smb_fname_dst->base_name);
7064 if (!NT_STATUS_IS_OK(status)) {
7065 TALLOC_FREE(dir_hnd);
7066 reply_nterror(req, status);
7070 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7071 smb_fname_src->base_name,
7072 smb_fname_dst->base_name));
7074 status = copy_file(ctx, conn, smb_fname_src,
7075 smb_fname_dst, ofun, count,
7076 target_is_directory);
7077 if (NT_STATUS_IS_OK(status)) {
7081 TALLOC_FREE(dir_hnd);
7085 reply_doserror(req, ERRDOS, error);
7089 reply_outbuf(req, 1, 0);
7090 SSVAL(req->outbuf,smb_vwv0,count);
7092 TALLOC_FREE(smb_fname_src);
7093 TALLOC_FREE(smb_fname_dst);
7094 TALLOC_FREE(fname_src);
7095 TALLOC_FREE(fname_dst);
7096 TALLOC_FREE(fname_src_mask);
7097 TALLOC_FREE(fname_src_dir);
7099 END_PROFILE(SMBcopy);
7104 #define DBGC_CLASS DBGC_LOCKING
7106 /****************************************************************************
7107 Get a lock pid, dealing with large count requests.
7108 ****************************************************************************/
7110 uint32 get_lock_pid(const uint8_t *data, int data_offset,
7111 bool large_file_format)
7113 if(!large_file_format)
7114 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
7116 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7119 /****************************************************************************
7120 Get a lock count, dealing with large count requests.
7121 ****************************************************************************/
7123 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7124 bool large_file_format)
7128 if(!large_file_format) {
7129 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7132 #if defined(HAVE_LONGLONG)
7133 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7134 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7135 #else /* HAVE_LONGLONG */
7138 * NT4.x seems to be broken in that it sends large file (64 bit)
7139 * lockingX calls even if the CAP_LARGE_FILES was *not*
7140 * negotiated. For boxes without large unsigned ints truncate the
7141 * lock count by dropping the top 32 bits.
7144 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7145 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7146 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7147 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7148 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7151 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7152 #endif /* HAVE_LONGLONG */
7158 #if !defined(HAVE_LONGLONG)
7159 /****************************************************************************
7160 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7161 ****************************************************************************/
7163 static uint32 map_lock_offset(uint32 high, uint32 low)
7167 uint32 highcopy = high;
7170 * Try and find out how many significant bits there are in high.
7173 for(i = 0; highcopy; i++)
7177 * We use 31 bits not 32 here as POSIX
7178 * lock offsets may not be negative.
7181 mask = (~0) << (31 - i);
7184 return 0; /* Fail. */
7190 #endif /* !defined(HAVE_LONGLONG) */
7192 /****************************************************************************
7193 Get a lock offset, dealing with large offset requests.
7194 ****************************************************************************/
7196 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7197 bool large_file_format, bool *err)
7199 uint64_t offset = 0;
7203 if(!large_file_format) {
7204 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7207 #if defined(HAVE_LONGLONG)
7208 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7209 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7210 #else /* HAVE_LONGLONG */
7213 * NT4.x seems to be broken in that it sends large file (64 bit)
7214 * lockingX calls even if the CAP_LARGE_FILES was *not*
7215 * negotiated. For boxes without large unsigned ints mangle the
7216 * lock offset by mapping the top 32 bits onto the lower 32.
7219 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7220 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7221 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7224 if((new_low = map_lock_offset(high, low)) == 0) {
7226 return (uint64_t)-1;
7229 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7230 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7231 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7232 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7235 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7236 #endif /* HAVE_LONGLONG */
7242 NTSTATUS smbd_do_locking(struct smb_request *req,
7246 uint16_t num_ulocks,
7247 struct smbd_lock_element *ulocks,
7249 struct smbd_lock_element *locks,
7252 connection_struct *conn = req->conn;
7254 NTSTATUS status = NT_STATUS_OK;
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 struct smbd_lock_element *e = &ulocks[i];
7263 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7264 "pid %u, file %s\n",
7267 (unsigned int)e->smbpid,
7270 if (e->brltype != UNLOCK_LOCK) {
7271 /* this can only happen with SMB2 */
7272 return NT_STATUS_INVALID_PARAMETER;
7275 status = do_unlock(smbd_messaging_context(),
7282 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7283 nt_errstr(status)));
7285 if (!NT_STATUS_IS_OK(status)) {
7290 /* Setup the timeout in seconds. */
7292 if (!lp_blocking_locks(SNUM(conn))) {
7296 /* Data now points at the beginning of the list
7297 of smb_lkrng structs */
7299 for(i = 0; i < (int)num_locks; i++) {
7300 struct smbd_lock_element *e = &locks[i];
7302 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for pid "
7303 "%u, file %s timeout = %d\n",
7306 (unsigned int)e->smbpid,
7310 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7311 struct blocking_lock_record *blr = NULL;
7313 if (lp_blocking_locks(SNUM(conn))) {
7315 /* Schedule a message to ourselves to
7316 remove the blocking lock record and
7317 return the right error. */
7319 blr = blocking_lock_cancel(fsp,
7325 NT_STATUS_FILE_LOCK_CONFLICT);
7327 return NT_STATUS_DOS(
7329 ERRcancelviolation);
7332 /* Remove a matching pending lock. */
7333 status = do_lock_cancel(fsp,
7340 bool blocking_lock = timeout ? true : false;
7341 bool defer_lock = false;
7342 struct byte_range_lock *br_lck;
7343 uint32_t block_smbpid;
7345 br_lck = do_lock(smbd_messaging_context(),
7357 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7358 /* Windows internal resolution for blocking locks seems
7359 to be about 200ms... Don't wait for less than that. JRA. */
7360 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7361 timeout = lp_lock_spin_time();
7366 /* This heuristic seems to match W2K3 very well. If a
7367 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7368 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7369 far as I can tell. Replacement for do_lock_spin(). JRA. */
7371 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7372 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7374 timeout = lp_lock_spin_time();
7377 if (br_lck && defer_lock) {
7379 * A blocking lock was requested. Package up
7380 * this smb into a queued request and push it
7381 * onto the blocking lock queue.
7383 if(push_blocking_lock_request(br_lck,
7394 TALLOC_FREE(br_lck);
7396 return NT_STATUS_OK;
7400 TALLOC_FREE(br_lck);
7403 if (!NT_STATUS_IS_OK(status)) {
7408 /* If any of the above locks failed, then we must unlock
7409 all of the previous locks (X/Open spec). */
7411 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7413 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7414 i = -1; /* we want to skip the for loop */
7418 * Ensure we don't do a remove on the lock that just failed,
7419 * as under POSIX rules, if we have a lock already there, we
7420 * will delete it (and we shouldn't) .....
7422 for(i--; i >= 0; i--) {
7423 struct smbd_lock_element *e = &locks[i];
7425 do_unlock(smbd_messaging_context(),
7435 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7436 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7438 return NT_STATUS_OK;
7441 /****************************************************************************
7442 Reply to a lockingX request.
7443 ****************************************************************************/
7445 void reply_lockingX(struct smb_request *req)
7447 connection_struct *conn = req->conn;
7449 unsigned char locktype;
7450 unsigned char oplocklevel;
7455 const uint8_t *data;
7456 bool large_file_format;
7458 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7459 struct smbd_lock_element *ulocks;
7460 struct smbd_lock_element *locks;
7463 START_PROFILE(SMBlockingX);
7466 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7467 END_PROFILE(SMBlockingX);
7471 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7472 locktype = CVAL(req->vwv+3, 0);
7473 oplocklevel = CVAL(req->vwv+3, 1);
7474 num_ulocks = SVAL(req->vwv+6, 0);
7475 num_locks = SVAL(req->vwv+7, 0);
7476 lock_timeout = IVAL(req->vwv+4, 0);
7477 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7479 if (!check_fsp(conn, req, fsp)) {
7480 END_PROFILE(SMBlockingX);
7486 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7487 /* we don't support these - and CANCEL_LOCK makes w2k
7488 and XP reboot so I don't really want to be
7489 compatible! (tridge) */
7490 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7491 END_PROFILE(SMBlockingX);
7495 /* Check if this is an oplock break on a file
7496 we have granted an oplock on.
7498 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7499 /* Client can insist on breaking to none. */
7500 bool break_to_none = (oplocklevel == 0);
7503 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7504 "for fnum = %d\n", (unsigned int)oplocklevel,
7508 * Make sure we have granted an exclusive or batch oplock on
7512 if (fsp->oplock_type == 0) {
7514 /* The Samba4 nbench simulator doesn't understand
7515 the difference between break to level2 and break
7516 to none from level2 - it sends oplock break
7517 replies in both cases. Don't keep logging an error
7518 message here - just ignore it. JRA. */
7520 DEBUG(5,("reply_lockingX: Error : oplock break from "
7521 "client for fnum = %d (oplock=%d) and no "
7522 "oplock granted on this file (%s).\n",
7523 fsp->fnum, fsp->oplock_type,
7526 /* if this is a pure oplock break request then don't
7528 if (num_locks == 0 && num_ulocks == 0) {
7529 END_PROFILE(SMBlockingX);
7532 END_PROFILE(SMBlockingX);
7533 reply_doserror(req, ERRDOS, ERRlock);
7538 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7540 result = remove_oplock(fsp);
7542 result = downgrade_oplock(fsp);
7546 DEBUG(0, ("reply_lockingX: error in removing "
7547 "oplock on file %s\n", fsp_str_dbg(fsp)));
7548 /* Hmmm. Is this panic justified? */
7549 smb_panic("internal tdb error");
7552 reply_to_oplock_break_requests(fsp);
7554 /* if this is a pure oplock break request then don't send a
7556 if (num_locks == 0 && num_ulocks == 0) {
7557 /* Sanity check - ensure a pure oplock break is not a
7559 if(CVAL(req->vwv+0, 0) != 0xff)
7560 DEBUG(0,("reply_lockingX: Error : pure oplock "
7561 "break is a chained %d request !\n",
7562 (unsigned int)CVAL(req->vwv+0, 0)));
7563 END_PROFILE(SMBlockingX);
7569 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7570 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7571 END_PROFILE(SMBlockingX);
7575 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7576 if (ulocks == NULL) {
7577 reply_nterror(req, NT_STATUS_NO_MEMORY);
7578 END_PROFILE(SMBlockingX);
7582 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7583 if (locks == NULL) {
7584 reply_nterror(req, NT_STATUS_NO_MEMORY);
7585 END_PROFILE(SMBlockingX);
7589 /* Data now points at the beginning of the list
7590 of smb_unlkrng structs */
7591 for(i = 0; i < (int)num_ulocks; i++) {
7592 ulocks[i].smbpid = get_lock_pid(data, i, large_file_format);
7593 ulocks[i].count = get_lock_count(data, i, large_file_format);
7594 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7595 ulocks[i].brltype = UNLOCK_LOCK;
7598 * There is no error code marked "stupid client bug".... :-).
7601 END_PROFILE(SMBlockingX);
7602 reply_doserror(req, ERRDOS, ERRnoaccess);
7607 /* Now do any requested locks */
7608 data += ((large_file_format ? 20 : 10)*num_ulocks);
7610 /* Data now points at the beginning of the list
7611 of smb_lkrng structs */
7613 for(i = 0; i < (int)num_locks; i++) {
7614 locks[i].smbpid = get_lock_pid(data, i, large_file_format);
7615 locks[i].count = get_lock_count(data, i, large_file_format);
7616 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7618 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7619 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7620 locks[i].brltype = PENDING_READ_LOCK;
7622 locks[i].brltype = READ_LOCK;
7625 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7626 locks[i].brltype = PENDING_WRITE_LOCK;
7628 locks[i].brltype = WRITE_LOCK;
7633 * There is no error code marked "stupid client bug".... :-).
7636 END_PROFILE(SMBlockingX);
7637 reply_doserror(req, ERRDOS, ERRnoaccess);
7642 status = smbd_do_locking(req, fsp,
7643 locktype, lock_timeout,
7647 if (!NT_STATUS_IS_OK(status)) {
7648 END_PROFILE(SMBlockingX);
7649 reply_nterror(req, status);
7653 END_PROFILE(SMBlockingX);
7657 reply_outbuf(req, 2, 0);
7659 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7660 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7662 END_PROFILE(SMBlockingX);
7667 #define DBGC_CLASS DBGC_ALL
7669 /****************************************************************************
7670 Reply to a SMBreadbmpx (read block multiplex) request.
7671 Always reply with an error, if someone has a platform really needs this,
7672 please contact vl@samba.org
7673 ****************************************************************************/
7675 void reply_readbmpx(struct smb_request *req)
7677 START_PROFILE(SMBreadBmpx);
7678 reply_doserror(req, ERRSRV, ERRuseSTD);
7679 END_PROFILE(SMBreadBmpx);
7683 /****************************************************************************
7684 Reply to a SMBreadbs (read block multiplex secondary) request.
7685 Always reply with an error, if someone has a platform really needs this,
7686 please contact vl@samba.org
7687 ****************************************************************************/
7689 void reply_readbs(struct smb_request *req)
7691 START_PROFILE(SMBreadBs);
7692 reply_doserror(req, ERRSRV, ERRuseSTD);
7693 END_PROFILE(SMBreadBs);
7697 /****************************************************************************
7698 Reply to a SMBsetattrE.
7699 ****************************************************************************/
7701 void reply_setattrE(struct smb_request *req)
7703 connection_struct *conn = req->conn;
7704 struct smb_file_time ft;
7708 START_PROFILE(SMBsetattrE);
7712 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7716 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7718 if(!fsp || (fsp->conn != conn)) {
7719 reply_doserror(req, ERRDOS, ERRbadfid);
7724 * Convert the DOS times into unix times.
7727 ft.atime = convert_time_t_to_timespec(
7728 srv_make_unix_date2(req->vwv+3));
7729 ft.mtime = convert_time_t_to_timespec(
7730 srv_make_unix_date2(req->vwv+5));
7731 ft.create_time = convert_time_t_to_timespec(
7732 srv_make_unix_date2(req->vwv+1));
7734 reply_outbuf(req, 0, 0);
7737 * Patch from Ray Frush <frush@engr.colostate.edu>
7738 * Sometimes times are sent as zero - ignore them.
7741 /* Ensure we have a valid stat struct for the source. */
7742 if (fsp->fh->fd != -1) {
7743 if (SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) == -1) {
7744 status = map_nt_error_from_unix(errno);
7745 reply_nterror(req, status);
7751 if (fsp->posix_open) {
7752 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name);
7754 ret = SMB_VFS_STAT(conn, fsp->fsp_name);
7757 status = map_nt_error_from_unix(errno);
7758 reply_nterror(req, status);
7763 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7764 if (!NT_STATUS_IS_OK(status)) {
7765 reply_doserror(req, ERRDOS, ERRnoaccess);
7769 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7772 (unsigned int)ft.atime.tv_sec,
7773 (unsigned int)ft.mtime.tv_sec,
7774 (unsigned int)ft.create_time.tv_sec
7777 END_PROFILE(SMBsetattrE);
7782 /* Back from the dead for OS/2..... JRA. */
7784 /****************************************************************************
7785 Reply to a SMBwritebmpx (write block multiplex primary) request.
7786 Always reply with an error, if someone has a platform really needs this,
7787 please contact vl@samba.org
7788 ****************************************************************************/
7790 void reply_writebmpx(struct smb_request *req)
7792 START_PROFILE(SMBwriteBmpx);
7793 reply_doserror(req, ERRSRV, ERRuseSTD);
7794 END_PROFILE(SMBwriteBmpx);
7798 /****************************************************************************
7799 Reply to a SMBwritebs (write block multiplex secondary) request.
7800 Always reply with an error, if someone has a platform really needs this,
7801 please contact vl@samba.org
7802 ****************************************************************************/
7804 void reply_writebs(struct smb_request *req)
7806 START_PROFILE(SMBwriteBs);
7807 reply_doserror(req, ERRSRV, ERRuseSTD);
7808 END_PROFILE(SMBwriteBs);
7812 /****************************************************************************
7813 Reply to a SMBgetattrE.
7814 ****************************************************************************/
7816 void reply_getattrE(struct smb_request *req)
7818 connection_struct *conn = req->conn;
7819 SMB_STRUCT_STAT sbuf;
7822 struct timespec create_ts;
7824 START_PROFILE(SMBgetattrE);
7827 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7828 END_PROFILE(SMBgetattrE);
7832 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7834 if(!fsp || (fsp->conn != conn)) {
7835 reply_doserror(req, ERRDOS, ERRbadfid);
7836 END_PROFILE(SMBgetattrE);
7840 /* Do an fstat on this file */
7841 if(fsp_stat(fsp, &sbuf)) {
7842 reply_nterror(req, map_nt_error_from_unix(errno));
7843 END_PROFILE(SMBgetattrE);
7847 fsp->fsp_name->st = sbuf;
7849 mode = dos_mode(conn, fsp->fsp_name);
7852 * Convert the times into dos times. Set create
7853 * date to be last modify date as UNIX doesn't save
7857 reply_outbuf(req, 11, 0);
7859 create_ts = sbuf.st_ex_btime;
7860 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7861 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7862 convert_timespec_to_time_t(sbuf.st_ex_atime));
7863 /* Should we check pending modtime here ? JRA */
7864 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7865 convert_timespec_to_time_t(sbuf.st_ex_mtime));
7868 SIVAL(req->outbuf, smb_vwv6, 0);
7869 SIVAL(req->outbuf, smb_vwv8, 0);
7871 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7872 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_ex_size);
7873 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7875 SSVAL(req->outbuf,smb_vwv10, mode);
7877 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7879 END_PROFILE(SMBgetattrE);