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
29 #include "smbd/globals.h"
30 #include "fake_file.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32 #include "rpc_client/cli_spoolss.h"
33 #include "rpc_client/init_spoolss.h"
34 #include "rpc_server/rpc_ncacn_np.h"
36 /****************************************************************************
37 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
38 path or anything including wildcards.
39 We're assuming here that '/' is not the second byte in any multibyte char
40 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
42 ****************************************************************************/
44 /* Custom version for processing POSIX paths. */
45 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
47 static NTSTATUS check_path_syntax_internal(char *path,
49 bool *p_last_component_contains_wcard)
53 NTSTATUS ret = NT_STATUS_OK;
54 bool start_of_name_component = True;
55 bool stream_started = false;
57 *p_last_component_contains_wcard = False;
64 return NT_STATUS_OBJECT_NAME_INVALID;
67 return NT_STATUS_OBJECT_NAME_INVALID;
69 if (strchr_m(&s[1], ':')) {
70 return NT_STATUS_OBJECT_NAME_INVALID;
76 if ((*s == ':') && !posix_path && !stream_started) {
77 if (*p_last_component_contains_wcard) {
78 return NT_STATUS_OBJECT_NAME_INVALID;
80 /* Stream names allow more characters than file names.
81 We're overloading posix_path here to allow a wider
82 range of characters. If stream_started is true this
83 is still a Windows path even if posix_path is true.
86 stream_started = true;
87 start_of_name_component = false;
91 return NT_STATUS_OBJECT_NAME_INVALID;
95 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
97 * Safe to assume is not the second part of a mb char
98 * as this is handled below.
100 /* Eat multiple '/' or '\\' */
101 while (IS_PATH_SEP(*s,posix_path)) {
104 if ((d != path) && (*s != '\0')) {
105 /* We only care about non-leading or trailing '/' or '\\' */
109 start_of_name_component = True;
111 *p_last_component_contains_wcard = False;
115 if (start_of_name_component) {
116 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
117 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
120 * No mb char starts with '.' so we're safe checking the directory separator here.
123 /* If we just added a '/' - delete it */
124 if ((d > path) && (*(d-1) == '/')) {
129 /* Are we at the start ? Can't go back further if so. */
131 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
134 /* Go back one level... */
135 /* We know this is safe as '/' cannot be part of a mb sequence. */
136 /* NOTE - if this assumption is invalid we are not in good shape... */
137 /* Decrement d first as d points to the *next* char to write into. */
138 for (d--; d > path; d--) {
142 s += 2; /* Else go past the .. */
143 /* We're still at the start of a name component, just the previous one. */
146 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
158 if (*s <= 0x1f || *s == '|') {
159 return NT_STATUS_OBJECT_NAME_INVALID;
167 *p_last_component_contains_wcard = True;
176 /* Get the size of the next MB character. */
177 next_codepoint(s,&siz);
195 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
197 return NT_STATUS_INVALID_PARAMETER;
200 start_of_name_component = False;
208 /****************************************************************************
209 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
210 No wildcards allowed.
211 ****************************************************************************/
213 NTSTATUS check_path_syntax(char *path)
216 return check_path_syntax_internal(path, False, &ignore);
219 /****************************************************************************
220 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
221 Wildcards allowed - p_contains_wcard returns true if the last component contained
223 ****************************************************************************/
225 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
227 return check_path_syntax_internal(path, False, p_contains_wcard);
230 /****************************************************************************
231 Check the path for a POSIX client.
232 We're assuming here that '/' is not the second byte in any multibyte char
233 set (a safe assumption).
234 ****************************************************************************/
236 NTSTATUS check_path_syntax_posix(char *path)
239 return check_path_syntax_internal(path, True, &ignore);
242 /****************************************************************************
243 Pull a string and check the path allowing a wilcard - provide for error return.
244 ****************************************************************************/
246 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
247 const char *base_ptr,
254 bool *contains_wcard)
260 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
264 *err = NT_STATUS_INVALID_PARAMETER;
268 *contains_wcard = False;
270 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
272 * For a DFS path the function parse_dfs_path()
273 * will do the path processing, just make a copy.
279 if (lp_posix_pathnames()) {
280 *err = check_path_syntax_posix(*pp_dest);
282 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
288 /****************************************************************************
289 Pull a string and check the path - provide for error return.
290 ****************************************************************************/
292 size_t srvstr_get_path(TALLOC_CTX *ctx,
293 const char *base_ptr,
302 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
303 src_len, flags, err, &ignore);
306 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
307 char **pp_dest, const char *src, int flags,
308 NTSTATUS *err, bool *contains_wcard)
310 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
311 pp_dest, src, smbreq_bufrem(req, src),
312 flags, err, contains_wcard);
315 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
316 char **pp_dest, const char *src, int flags,
320 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
321 flags, err, &ignore);
324 /****************************************************************************
325 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
326 ****************************************************************************/
328 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
331 if ((fsp == NULL) || (conn == NULL)) {
332 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
335 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
336 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
342 /****************************************************************************
343 Check if we have a correct fsp pointing to a file.
344 ****************************************************************************/
346 bool check_fsp(connection_struct *conn, struct smb_request *req,
349 if (!check_fsp_open(conn, req, fsp)) {
352 if (fsp->is_directory) {
353 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
356 if (fsp->fh->fd == -1) {
357 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
360 fsp->num_smb_operations++;
364 /****************************************************************************
365 Check if we have a correct fsp pointing to a quota fake file. Replacement for
366 the CHECK_NTQUOTA_HANDLE_OK macro.
367 ****************************************************************************/
369 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
372 if (!check_fsp_open(conn, req, fsp)) {
376 if (fsp->is_directory) {
380 if (fsp->fake_file_handle == NULL) {
384 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
388 if (fsp->fake_file_handle->private_data == NULL) {
395 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
396 const char *name, int name_type)
399 char *trim_name_type;
400 const char *retarget_parm;
403 int retarget_type = 0x20;
404 int retarget_port = 139;
405 struct sockaddr_storage retarget_addr;
406 struct sockaddr_in *in_addr;
410 if (get_socket_port(sconn->sock) != 139) {
414 trim_name = talloc_strdup(talloc_tos(), name);
415 if (trim_name == NULL) {
418 trim_char(trim_name, ' ', ' ');
420 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
422 if (trim_name_type == NULL) {
426 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
427 trim_name_type, NULL);
428 if (retarget_parm == NULL) {
429 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
432 if (retarget_parm == NULL) {
436 retarget = talloc_strdup(trim_name, retarget_parm);
437 if (retarget == NULL) {
441 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
443 p = strchr(retarget, ':');
446 retarget_port = atoi(p);
449 p = strchr_m(retarget, '#');
452 sscanf(p, "%x", &retarget_type);
455 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
457 DEBUG(10, ("could not resolve %s\n", retarget));
461 if (retarget_addr.ss_family != AF_INET) {
462 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
466 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
468 _smb_setlen(outbuf, 6);
469 SCVAL(outbuf, 0, 0x84);
470 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
471 *(uint16_t *)(outbuf+8) = htons(retarget_port);
473 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
475 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
481 TALLOC_FREE(trim_name);
485 /****************************************************************************
486 Reply to a (netbios-level) special message.
487 ****************************************************************************/
489 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
491 int msg_type = CVAL(inbuf,0);
492 int msg_flags = CVAL(inbuf,1);
494 * We only really use 4 bytes of the outbuf, but for the smb_setlen
495 * calculation & friends (srv_send_smb uses that) we need the full smb
498 char outbuf[smb_size];
500 memset(outbuf, '\0', sizeof(outbuf));
502 smb_setlen(outbuf,0);
505 case 0x81: /* session request */
507 /* inbuf_size is guarenteed to be at least 4. */
509 int name_type1, name_type2;
510 int name_len1, name_len2;
514 if (sconn->nbt.got_session) {
515 exit_server_cleanly("multiple session request not permitted");
518 SCVAL(outbuf,0,0x82);
521 /* inbuf_size is guaranteed to be at least 4. */
522 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
523 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
524 DEBUG(0,("Invalid name length in session request\n"));
527 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
528 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
529 DEBUG(0,("Invalid name length in session request\n"));
533 name_type1 = name_extract((unsigned char *)inbuf,
534 inbuf_size,(unsigned int)4,name1);
535 name_type2 = name_extract((unsigned char *)inbuf,
536 inbuf_size,(unsigned int)(4 + name_len1),name2);
538 if (name_type1 == -1 || name_type2 == -1) {
539 DEBUG(0,("Invalid name type in session request\n"));
543 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
544 name1, name_type1, name2, name_type2));
546 if (netbios_session_retarget(sconn, name1, name_type1)) {
547 exit_server_cleanly("retargeted client");
551 * Windows NT/2k uses "*SMBSERVER" and XP uses
552 * "*SMBSERV" arrggg!!!
554 if (strequal(name1, "*SMBSERVER ")
555 || strequal(name1, "*SMBSERV ")) {
556 fstrcpy(name1, sconn->client_id.addr);
559 set_local_machine_name(name1, True);
560 set_remote_machine_name(name2, True);
562 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
563 get_local_machine_name(), get_remote_machine_name(),
566 if (name_type2 == 'R') {
567 /* We are being asked for a pathworks session ---
569 SCVAL(outbuf, 0,0x83);
573 /* only add the client's machine name to the list
574 of possibly valid usernames if we are operating
575 in share mode security */
576 if (lp_security() == SEC_SHARE) {
577 add_session_user(sconn, get_remote_machine_name());
580 reload_services(sconn->msg_ctx, sconn->sock, True);
583 sconn->nbt.got_session = true;
587 case 0x89: /* session keepalive request
588 (some old clients produce this?) */
589 SCVAL(outbuf,0,SMBkeepalive);
593 case 0x82: /* positive session response */
594 case 0x83: /* negative session response */
595 case 0x84: /* retarget session response */
596 DEBUG(0,("Unexpected session response\n"));
599 case SMBkeepalive: /* session keepalive */
604 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
605 msg_type, msg_flags));
607 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
611 /****************************************************************************
613 conn POINTER CAN BE NULL HERE !
614 ****************************************************************************/
616 void reply_tcon(struct smb_request *req)
618 connection_struct *conn = req->conn;
620 char *service_buf = NULL;
621 char *password = NULL;
626 DATA_BLOB password_blob;
627 TALLOC_CTX *ctx = talloc_tos();
628 struct smbd_server_connection *sconn = req->sconn;
630 START_PROFILE(SMBtcon);
632 if (req->buflen < 4) {
633 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
634 END_PROFILE(SMBtcon);
638 p = (const char *)req->buf + 1;
639 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
641 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
643 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
646 if (service_buf == NULL || password == NULL || dev == NULL) {
647 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
648 END_PROFILE(SMBtcon);
651 p = strrchr_m(service_buf,'\\');
655 service = service_buf;
658 password_blob = data_blob(password, pwlen+1);
660 conn = make_connection(sconn,service,password_blob,dev,
661 req->vuid,&nt_status);
664 data_blob_clear_free(&password_blob);
667 reply_nterror(req, nt_status);
668 END_PROFILE(SMBtcon);
672 reply_outbuf(req, 2, 0);
673 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
674 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
675 SSVAL(req->outbuf,smb_tid,conn->cnum);
677 DEBUG(3,("tcon service=%s cnum=%d\n",
678 service, conn->cnum));
680 END_PROFILE(SMBtcon);
684 /****************************************************************************
685 Reply to a tcon and X.
686 conn POINTER CAN BE NULL HERE !
687 ****************************************************************************/
689 void reply_tcon_and_X(struct smb_request *req)
691 connection_struct *conn = req->conn;
692 const char *service = NULL;
694 TALLOC_CTX *ctx = talloc_tos();
695 /* what the cleint thinks the device is */
696 char *client_devicetype = NULL;
697 /* what the server tells the client the share represents */
698 const char *server_devicetype;
704 struct smbd_server_connection *sconn = req->sconn;
706 START_PROFILE(SMBtconX);
709 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
710 END_PROFILE(SMBtconX);
714 passlen = SVAL(req->vwv+3, 0);
715 tcon_flags = SVAL(req->vwv+2, 0);
717 /* we might have to close an old one */
718 if ((tcon_flags & 0x1) && conn) {
719 close_cnum(conn,req->vuid);
724 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
725 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
726 END_PROFILE(SMBtconX);
730 if (sconn->smb1.negprot.encrypted_passwords) {
731 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
732 if (lp_security() == SEC_SHARE) {
734 * Security = share always has a pad byte
735 * after the password.
737 p = (const char *)req->buf + passlen + 1;
739 p = (const char *)req->buf + passlen;
742 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
743 /* Ensure correct termination */
744 password.data[passlen]=0;
745 p = (const char *)req->buf + passlen + 1;
748 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
751 data_blob_clear_free(&password);
752 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
753 END_PROFILE(SMBtconX);
758 * the service name can be either: \\server\share
759 * or share directly like on the DELL PowerVault 705
762 q = strchr_m(path+2,'\\');
764 data_blob_clear_free(&password);
765 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
766 END_PROFILE(SMBtconX);
774 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
775 &client_devicetype, p,
776 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
778 if (client_devicetype == NULL) {
779 data_blob_clear_free(&password);
780 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
781 END_PROFILE(SMBtconX);
785 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
787 conn = make_connection(sconn, service, password, client_devicetype,
788 req->vuid, &nt_status);
791 data_blob_clear_free(&password);
794 reply_nterror(req, nt_status);
795 END_PROFILE(SMBtconX);
800 server_devicetype = "IPC";
801 else if ( IS_PRINT(conn) )
802 server_devicetype = "LPT1:";
804 server_devicetype = "A:";
806 if (get_Protocol() < PROTOCOL_NT1) {
807 reply_outbuf(req, 2, 0);
808 if (message_push_string(&req->outbuf, server_devicetype,
809 STR_TERMINATE|STR_ASCII) == -1) {
810 reply_nterror(req, NT_STATUS_NO_MEMORY);
811 END_PROFILE(SMBtconX);
815 /* NT sets the fstype of IPC$ to the null string */
816 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
818 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
819 /* Return permissions. */
823 reply_outbuf(req, 7, 0);
826 perm1 = FILE_ALL_ACCESS;
827 perm2 = FILE_ALL_ACCESS;
829 perm1 = CAN_WRITE(conn) ?
834 SIVAL(req->outbuf, smb_vwv3, perm1);
835 SIVAL(req->outbuf, smb_vwv5, perm2);
837 reply_outbuf(req, 3, 0);
840 if ((message_push_string(&req->outbuf, server_devicetype,
841 STR_TERMINATE|STR_ASCII) == -1)
842 || (message_push_string(&req->outbuf, fstype,
843 STR_TERMINATE) == -1)) {
844 reply_nterror(req, NT_STATUS_NO_MEMORY);
845 END_PROFILE(SMBtconX);
849 /* what does setting this bit do? It is set by NT4 and
850 may affect the ability to autorun mounted cdroms */
851 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
852 (lp_csc_policy(SNUM(conn)) << 2));
854 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
855 DEBUG(2,("Serving %s as a Dfs root\n",
856 lp_servicename(SNUM(conn)) ));
857 SSVAL(req->outbuf, smb_vwv2,
858 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
863 DEBUG(3,("tconX service=%s \n",
866 /* set the incoming and outgoing tid to the just created one */
867 SSVAL(req->inbuf,smb_tid,conn->cnum);
868 SSVAL(req->outbuf,smb_tid,conn->cnum);
870 END_PROFILE(SMBtconX);
872 req->tid = conn->cnum;
877 /****************************************************************************
878 Reply to an unknown type.
879 ****************************************************************************/
881 void reply_unknown_new(struct smb_request *req, uint8 type)
883 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
884 smb_fn_name(type), type, type));
885 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
889 /****************************************************************************
891 conn POINTER CAN BE NULL HERE !
892 ****************************************************************************/
894 void reply_ioctl(struct smb_request *req)
896 connection_struct *conn = req->conn;
903 START_PROFILE(SMBioctl);
906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
907 END_PROFILE(SMBioctl);
911 device = SVAL(req->vwv+1, 0);
912 function = SVAL(req->vwv+2, 0);
913 ioctl_code = (device << 16) + function;
915 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
917 switch (ioctl_code) {
918 case IOCTL_QUERY_JOB_INFO:
922 reply_force_doserror(req, ERRSRV, ERRnosupport);
923 END_PROFILE(SMBioctl);
927 reply_outbuf(req, 8, replysize+1);
928 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
929 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
930 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
931 p = smb_buf(req->outbuf);
932 memset(p, '\0', replysize+1); /* valgrind-safe. */
933 p += 1; /* Allow for alignment */
935 switch (ioctl_code) {
936 case IOCTL_QUERY_JOB_INFO:
938 files_struct *fsp = file_fsp(
939 req, SVAL(req->vwv+0, 0));
941 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
942 END_PROFILE(SMBioctl);
946 if (fsp->print_file) {
947 SSVAL(p, 0, fsp->print_file->rap_jobid);
951 srvstr_push((char *)req->outbuf, req->flags2, p+2,
953 STR_TERMINATE|STR_ASCII);
955 srvstr_push((char *)req->outbuf, req->flags2,
956 p+18, lp_servicename(SNUM(conn)),
957 13, STR_TERMINATE|STR_ASCII);
965 END_PROFILE(SMBioctl);
969 /****************************************************************************
970 Strange checkpath NTSTATUS mapping.
971 ****************************************************************************/
973 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
975 /* Strange DOS error code semantics only for checkpath... */
976 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
977 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
978 /* We need to map to ERRbadpath */
979 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
985 /****************************************************************************
986 Reply to a checkpath.
987 ****************************************************************************/
989 void reply_checkpath(struct smb_request *req)
991 connection_struct *conn = req->conn;
992 struct smb_filename *smb_fname = NULL;
995 TALLOC_CTX *ctx = talloc_tos();
997 START_PROFILE(SMBcheckpath);
999 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1000 STR_TERMINATE, &status);
1002 if (!NT_STATUS_IS_OK(status)) {
1003 status = map_checkpath_error(req->flags2, status);
1004 reply_nterror(req, status);
1005 END_PROFILE(SMBcheckpath);
1009 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1011 status = filename_convert(ctx,
1013 req->flags2 & FLAGS2_DFS_PATHNAMES,
1019 if (!NT_STATUS_IS_OK(status)) {
1020 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1021 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1022 ERRSRV, ERRbadpath);
1023 END_PROFILE(SMBcheckpath);
1029 if (!VALID_STAT(smb_fname->st) &&
1030 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1031 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1032 smb_fname_str_dbg(smb_fname), strerror(errno)));
1033 status = map_nt_error_from_unix(errno);
1037 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1038 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1039 ERRDOS, ERRbadpath);
1043 reply_outbuf(req, 0, 0);
1046 /* We special case this - as when a Windows machine
1047 is parsing a path is steps through the components
1048 one at a time - if a component fails it expects
1049 ERRbadpath, not ERRbadfile.
1051 status = map_checkpath_error(req->flags2, status);
1052 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1054 * Windows returns different error codes if
1055 * the parent directory is valid but not the
1056 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1057 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1058 * if the path is invalid.
1060 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1061 ERRDOS, ERRbadpath);
1065 reply_nterror(req, status);
1068 TALLOC_FREE(smb_fname);
1069 END_PROFILE(SMBcheckpath);
1073 /****************************************************************************
1075 ****************************************************************************/
1077 void reply_getatr(struct smb_request *req)
1079 connection_struct *conn = req->conn;
1080 struct smb_filename *smb_fname = NULL;
1087 TALLOC_CTX *ctx = talloc_tos();
1088 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1090 START_PROFILE(SMBgetatr);
1092 p = (const char *)req->buf + 1;
1093 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1094 if (!NT_STATUS_IS_OK(status)) {
1095 reply_nterror(req, status);
1099 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1100 under WfWg - weird! */
1101 if (*fname == '\0') {
1102 mode = aHIDDEN | aDIR;
1103 if (!CAN_WRITE(conn)) {
1109 status = filename_convert(ctx,
1111 req->flags2 & FLAGS2_DFS_PATHNAMES,
1116 if (!NT_STATUS_IS_OK(status)) {
1117 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1118 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1119 ERRSRV, ERRbadpath);
1122 reply_nterror(req, status);
1125 if (!VALID_STAT(smb_fname->st) &&
1126 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1127 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1128 smb_fname_str_dbg(smb_fname),
1130 reply_nterror(req, map_nt_error_from_unix(errno));
1134 mode = dos_mode(conn, smb_fname);
1135 size = smb_fname->st.st_ex_size;
1137 if (ask_sharemode) {
1138 struct timespec write_time_ts;
1139 struct file_id fileid;
1141 ZERO_STRUCT(write_time_ts);
1142 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1143 get_file_infos(fileid, NULL, &write_time_ts);
1144 if (!null_timespec(write_time_ts)) {
1145 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1149 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1155 reply_outbuf(req, 10, 0);
1157 SSVAL(req->outbuf,smb_vwv0,mode);
1158 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1159 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1161 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1163 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1165 if (get_Protocol() >= PROTOCOL_NT1) {
1166 SSVAL(req->outbuf, smb_flg2,
1167 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1170 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1171 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1174 TALLOC_FREE(smb_fname);
1176 END_PROFILE(SMBgetatr);
1180 /****************************************************************************
1182 ****************************************************************************/
1184 void reply_setatr(struct smb_request *req)
1186 struct smb_file_time ft;
1187 connection_struct *conn = req->conn;
1188 struct smb_filename *smb_fname = NULL;
1194 TALLOC_CTX *ctx = talloc_tos();
1196 START_PROFILE(SMBsetatr);
1201 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1205 p = (const char *)req->buf + 1;
1206 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1207 if (!NT_STATUS_IS_OK(status)) {
1208 reply_nterror(req, status);
1212 status = filename_convert(ctx,
1214 req->flags2 & FLAGS2_DFS_PATHNAMES,
1219 if (!NT_STATUS_IS_OK(status)) {
1220 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1221 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1222 ERRSRV, ERRbadpath);
1225 reply_nterror(req, status);
1229 if (smb_fname->base_name[0] == '.' &&
1230 smb_fname->base_name[1] == '\0') {
1232 * Not sure here is the right place to catch this
1233 * condition. Might be moved to somewhere else later -- vl
1235 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1239 mode = SVAL(req->vwv+0, 0);
1240 mtime = srv_make_unix_date3(req->vwv+1);
1242 ft.mtime = convert_time_t_to_timespec(mtime);
1243 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1244 if (!NT_STATUS_IS_OK(status)) {
1245 reply_nterror(req, status);
1249 if (mode != FILE_ATTRIBUTE_NORMAL) {
1250 if (VALID_STAT_OF_DIR(smb_fname->st))
1255 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1257 reply_nterror(req, map_nt_error_from_unix(errno));
1262 reply_outbuf(req, 0, 0);
1264 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1267 TALLOC_FREE(smb_fname);
1268 END_PROFILE(SMBsetatr);
1272 /****************************************************************************
1274 ****************************************************************************/
1276 void reply_dskattr(struct smb_request *req)
1278 connection_struct *conn = req->conn;
1279 uint64_t dfree,dsize,bsize;
1280 START_PROFILE(SMBdskattr);
1282 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1283 reply_nterror(req, map_nt_error_from_unix(errno));
1284 END_PROFILE(SMBdskattr);
1288 reply_outbuf(req, 5, 0);
1290 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1291 double total_space, free_space;
1292 /* we need to scale this to a number that DOS6 can handle. We
1293 use floating point so we can handle large drives on systems
1294 that don't have 64 bit integers
1296 we end up displaying a maximum of 2G to DOS systems
1298 total_space = dsize * (double)bsize;
1299 free_space = dfree * (double)bsize;
1301 dsize = (uint64_t)((total_space+63*512) / (64*512));
1302 dfree = (uint64_t)((free_space+63*512) / (64*512));
1304 if (dsize > 0xFFFF) dsize = 0xFFFF;
1305 if (dfree > 0xFFFF) dfree = 0xFFFF;
1307 SSVAL(req->outbuf,smb_vwv0,dsize);
1308 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1309 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1310 SSVAL(req->outbuf,smb_vwv3,dfree);
1312 SSVAL(req->outbuf,smb_vwv0,dsize);
1313 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1314 SSVAL(req->outbuf,smb_vwv2,512);
1315 SSVAL(req->outbuf,smb_vwv3,dfree);
1318 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1320 END_PROFILE(SMBdskattr);
1325 * Utility function to split the filename from the directory.
1327 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1328 char **fname_dir_out,
1329 char **fname_mask_out)
1331 const char *p = NULL;
1332 char *fname_dir = NULL;
1333 char *fname_mask = NULL;
1335 p = strrchr_m(fname_in, '/');
1337 fname_dir = talloc_strdup(ctx, ".");
1338 fname_mask = talloc_strdup(ctx, fname_in);
1340 fname_dir = talloc_strndup(ctx, fname_in,
1341 PTR_DIFF(p, fname_in));
1342 fname_mask = talloc_strdup(ctx, p+1);
1345 if (!fname_dir || !fname_mask) {
1346 TALLOC_FREE(fname_dir);
1347 TALLOC_FREE(fname_mask);
1348 return NT_STATUS_NO_MEMORY;
1351 *fname_dir_out = fname_dir;
1352 *fname_mask_out = fname_mask;
1353 return NT_STATUS_OK;
1356 /****************************************************************************
1358 Can be called from SMBsearch, SMBffirst or SMBfunique.
1359 ****************************************************************************/
1361 void reply_search(struct smb_request *req)
1363 connection_struct *conn = req->conn;
1365 const char *mask = NULL;
1366 char *directory = NULL;
1367 struct smb_filename *smb_fname = NULL;
1371 struct timespec date;
1373 unsigned int numentries = 0;
1374 unsigned int maxentries = 0;
1375 bool finished = False;
1380 bool check_descend = False;
1381 bool expect_close = False;
1383 bool mask_contains_wcard = False;
1384 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1385 TALLOC_CTX *ctx = talloc_tos();
1386 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1387 struct dptr_struct *dirptr = NULL;
1388 struct smbd_server_connection *sconn = req->sconn;
1390 START_PROFILE(SMBsearch);
1393 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1397 if (lp_posix_pathnames()) {
1398 reply_unknown_new(req, req->cmd);
1402 /* If we were called as SMBffirst then we must expect close. */
1403 if(req->cmd == SMBffirst) {
1404 expect_close = True;
1407 reply_outbuf(req, 1, 3);
1408 maxentries = SVAL(req->vwv+0, 0);
1409 dirtype = SVAL(req->vwv+1, 0);
1410 p = (const char *)req->buf + 1;
1411 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1412 &nt_status, &mask_contains_wcard);
1413 if (!NT_STATUS_IS_OK(nt_status)) {
1414 reply_nterror(req, nt_status);
1419 status_len = SVAL(p, 0);
1422 /* dirtype &= ~aDIR; */
1424 if (status_len == 0) {
1425 nt_status = filename_convert(ctx, conn,
1426 req->flags2 & FLAGS2_DFS_PATHNAMES,
1428 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1429 &mask_contains_wcard,
1431 if (!NT_STATUS_IS_OK(nt_status)) {
1432 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1433 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1434 ERRSRV, ERRbadpath);
1437 reply_nterror(req, nt_status);
1441 directory = smb_fname->base_name;
1443 p = strrchr_m(directory,'/');
1444 if ((p != NULL) && (*directory != '/')) {
1446 directory = talloc_strndup(ctx, directory,
1447 PTR_DIFF(p, directory));
1450 directory = talloc_strdup(ctx,".");
1454 reply_nterror(req, NT_STATUS_NO_MEMORY);
1458 memset((char *)status,'\0',21);
1459 SCVAL(status,0,(dirtype & 0x1F));
1461 nt_status = dptr_create(conn,
1467 mask_contains_wcard,
1470 if (!NT_STATUS_IS_OK(nt_status)) {
1471 reply_nterror(req, nt_status);
1474 dptr_num = dptr_dnum(dirptr);
1477 const char *dirpath;
1479 memcpy(status,p,21);
1480 status_dirtype = CVAL(status,0) & 0x1F;
1481 if (status_dirtype != (dirtype & 0x1F)) {
1482 dirtype = status_dirtype;
1485 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1489 dirpath = dptr_path(sconn, dptr_num);
1490 directory = talloc_strdup(ctx, dirpath);
1492 reply_nterror(req, NT_STATUS_NO_MEMORY);
1496 mask = dptr_wcard(sconn, dptr_num);
1501 * For a 'continue' search we have no string. So
1502 * check from the initial saved string.
1504 mask_contains_wcard = ms_has_wild(mask);
1505 dirtype = dptr_attr(sconn, dptr_num);
1508 DEBUG(4,("dptr_num is %d\n",dptr_num));
1510 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1511 dptr_init_search_op(dirptr);
1513 if ((dirtype&0x1F) == aVOLID) {
1514 char buf[DIR_STRUCT_SIZE];
1515 memcpy(buf,status,21);
1516 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1517 0,aVOLID,0,!allow_long_path_components)) {
1518 reply_nterror(req, NT_STATUS_NO_MEMORY);
1521 dptr_fill(sconn, buf+12,dptr_num);
1522 if (dptr_zero(buf+12) && (status_len==0)) {
1527 if (message_push_blob(&req->outbuf,
1528 data_blob_const(buf, sizeof(buf)))
1530 reply_nterror(req, NT_STATUS_NO_MEMORY);
1538 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1541 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1542 directory,lp_dontdescend(SNUM(conn))));
1543 if (in_list(directory, 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);
1572 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1575 if (message_push_blob(&req->outbuf,
1576 data_blob_const(buf, sizeof(buf)))
1578 reply_nterror(req, NT_STATUS_NO_MEMORY);
1588 /* If we were called as SMBffirst with smb_search_id == NULL
1589 and no entries were found then return error and close dirptr
1592 if (numentries == 0) {
1593 dptr_close(sconn, &dptr_num);
1594 } else if(expect_close && status_len == 0) {
1595 /* Close the dptr - we know it's gone */
1596 dptr_close(sconn, &dptr_num);
1599 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1600 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1601 dptr_close(sconn, &dptr_num);
1604 if ((numentries == 0) && !mask_contains_wcard) {
1605 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1609 SSVAL(req->outbuf,smb_vwv0,numentries);
1610 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1611 SCVAL(smb_buf(req->outbuf),0,5);
1612 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1614 /* The replies here are never long name. */
1615 SSVAL(req->outbuf, smb_flg2,
1616 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1617 if (!allow_long_path_components) {
1618 SSVAL(req->outbuf, smb_flg2,
1619 SVAL(req->outbuf, smb_flg2)
1620 & (~FLAGS2_LONG_PATH_COMPONENTS));
1623 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1624 SSVAL(req->outbuf, smb_flg2,
1625 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1627 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1628 smb_fn_name(req->cmd),
1635 TALLOC_FREE(directory);
1636 TALLOC_FREE(smb_fname);
1637 END_PROFILE(SMBsearch);
1641 /****************************************************************************
1642 Reply to a fclose (stop directory search).
1643 ****************************************************************************/
1645 void reply_fclose(struct smb_request *req)
1653 bool path_contains_wcard = False;
1654 TALLOC_CTX *ctx = talloc_tos();
1655 struct smbd_server_connection *sconn = req->sconn;
1657 START_PROFILE(SMBfclose);
1659 if (lp_posix_pathnames()) {
1660 reply_unknown_new(req, req->cmd);
1661 END_PROFILE(SMBfclose);
1665 p = (const char *)req->buf + 1;
1666 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1667 &err, &path_contains_wcard);
1668 if (!NT_STATUS_IS_OK(err)) {
1669 reply_nterror(req, err);
1670 END_PROFILE(SMBfclose);
1674 status_len = SVAL(p,0);
1677 if (status_len == 0) {
1678 reply_force_doserror(req, ERRSRV, ERRsrverror);
1679 END_PROFILE(SMBfclose);
1683 memcpy(status,p,21);
1685 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1686 /* Close the dptr - we know it's gone */
1687 dptr_close(sconn, &dptr_num);
1690 reply_outbuf(req, 1, 0);
1691 SSVAL(req->outbuf,smb_vwv0,0);
1693 DEBUG(3,("search close\n"));
1695 END_PROFILE(SMBfclose);
1699 /****************************************************************************
1701 ****************************************************************************/
1703 void reply_open(struct smb_request *req)
1705 connection_struct *conn = req->conn;
1706 struct smb_filename *smb_fname = NULL;
1718 uint32 create_disposition;
1719 uint32 create_options = 0;
1720 uint32_t private_flags = 0;
1722 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1723 TALLOC_CTX *ctx = talloc_tos();
1725 START_PROFILE(SMBopen);
1728 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1732 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1733 deny_mode = SVAL(req->vwv+0, 0);
1734 dos_attr = SVAL(req->vwv+1, 0);
1736 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1737 STR_TERMINATE, &status);
1738 if (!NT_STATUS_IS_OK(status)) {
1739 reply_nterror(req, status);
1743 status = filename_convert(ctx,
1745 req->flags2 & FLAGS2_DFS_PATHNAMES,
1750 if (!NT_STATUS_IS_OK(status)) {
1751 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1752 reply_botherror(req,
1753 NT_STATUS_PATH_NOT_COVERED,
1754 ERRSRV, ERRbadpath);
1757 reply_nterror(req, status);
1761 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1762 OPENX_FILE_EXISTS_OPEN, &access_mask,
1763 &share_mode, &create_disposition,
1764 &create_options, &private_flags)) {
1765 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1769 status = SMB_VFS_CREATE_FILE(
1772 0, /* root_dir_fid */
1773 smb_fname, /* fname */
1774 access_mask, /* access_mask */
1775 share_mode, /* share_access */
1776 create_disposition, /* create_disposition*/
1777 create_options, /* create_options */
1778 dos_attr, /* file_attributes */
1779 oplock_request, /* oplock_request */
1780 0, /* allocation_size */
1787 if (!NT_STATUS_IS_OK(status)) {
1788 if (open_was_deferred(req->mid)) {
1789 /* We have re-scheduled this call. */
1792 reply_openerror(req, status);
1796 size = smb_fname->st.st_ex_size;
1797 fattr = dos_mode(conn, smb_fname);
1799 /* Deal with other possible opens having a modified
1801 if (ask_sharemode) {
1802 struct timespec write_time_ts;
1804 ZERO_STRUCT(write_time_ts);
1805 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1806 if (!null_timespec(write_time_ts)) {
1807 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1811 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1814 DEBUG(3,("attempt to open a directory %s\n",
1816 close_file(req, fsp, ERROR_CLOSE);
1817 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1818 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 uint32_t private_flags = 0;
1882 TALLOC_CTX *ctx = talloc_tos();
1884 START_PROFILE(SMBopenX);
1886 if (req->wct < 15) {
1887 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1891 open_flags = SVAL(req->vwv+2, 0);
1892 deny_mode = SVAL(req->vwv+3, 0);
1893 smb_attr = SVAL(req->vwv+5, 0);
1894 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1895 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1896 oplock_request = ex_oplock_request | core_oplock_request;
1897 smb_ofun = SVAL(req->vwv+8, 0);
1898 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1900 /* If it's an IPC, pass off the pipe handler. */
1902 if (lp_nt_pipe_support()) {
1903 reply_open_pipe_and_X(conn, req);
1905 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1910 /* XXXX we need to handle passed times, sattr and flags */
1911 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1912 STR_TERMINATE, &status);
1913 if (!NT_STATUS_IS_OK(status)) {
1914 reply_nterror(req, status);
1918 status = filename_convert(ctx,
1920 req->flags2 & FLAGS2_DFS_PATHNAMES,
1925 if (!NT_STATUS_IS_OK(status)) {
1926 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1927 reply_botherror(req,
1928 NT_STATUS_PATH_NOT_COVERED,
1929 ERRSRV, ERRbadpath);
1932 reply_nterror(req, status);
1936 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1937 &access_mask, &share_mode,
1938 &create_disposition,
1941 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1945 status = SMB_VFS_CREATE_FILE(
1948 0, /* root_dir_fid */
1949 smb_fname, /* fname */
1950 access_mask, /* access_mask */
1951 share_mode, /* share_access */
1952 create_disposition, /* create_disposition*/
1953 create_options, /* create_options */
1954 smb_attr, /* file_attributes */
1955 oplock_request, /* oplock_request */
1956 0, /* allocation_size */
1961 &smb_action); /* pinfo */
1963 if (!NT_STATUS_IS_OK(status)) {
1964 if (open_was_deferred(req->mid)) {
1965 /* We have re-scheduled this call. */
1968 reply_openerror(req, status);
1972 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1973 if the file is truncated or created. */
1974 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1975 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1976 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1977 close_file(req, fsp, ERROR_CLOSE);
1978 reply_nterror(req, NT_STATUS_DISK_FULL);
1981 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1983 close_file(req, fsp, ERROR_CLOSE);
1984 reply_nterror(req, NT_STATUS_DISK_FULL);
1987 smb_fname->st.st_ex_size =
1988 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1991 fattr = dos_mode(conn, smb_fname);
1992 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1994 close_file(req, fsp, ERROR_CLOSE);
1995 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1999 /* If the caller set the extended oplock request bit
2000 and we granted one (by whatever means) - set the
2001 correct bit for extended oplock reply.
2004 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2005 smb_action |= EXTENDED_OPLOCK_GRANTED;
2008 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2009 smb_action |= EXTENDED_OPLOCK_GRANTED;
2012 /* If the caller set the core oplock request bit
2013 and we granted one (by whatever means) - set the
2014 correct bit for core oplock reply.
2017 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2018 reply_outbuf(req, 19, 0);
2020 reply_outbuf(req, 15, 0);
2023 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2024 SCVAL(req->outbuf, smb_flg,
2025 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2028 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2029 SCVAL(req->outbuf, smb_flg,
2030 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2033 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2034 SSVAL(req->outbuf,smb_vwv3,fattr);
2035 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2036 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2038 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2040 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2041 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2042 SSVAL(req->outbuf,smb_vwv11,smb_action);
2044 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2045 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2050 TALLOC_FREE(smb_fname);
2051 END_PROFILE(SMBopenX);
2055 /****************************************************************************
2056 Reply to a SMBulogoffX.
2057 ****************************************************************************/
2059 void reply_ulogoffX(struct smb_request *req)
2061 struct smbd_server_connection *sconn = req->sconn;
2064 START_PROFILE(SMBulogoffX);
2066 vuser = get_valid_user_struct(sconn, req->vuid);
2069 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2073 /* in user level security we are supposed to close any files
2074 open by this user */
2075 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2076 file_close_user(req->vuid);
2079 invalidate_vuid(sconn, req->vuid);
2081 reply_outbuf(req, 2, 0);
2083 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2085 END_PROFILE(SMBulogoffX);
2086 req->vuid = UID_FIELD_INVALID;
2090 /****************************************************************************
2091 Reply to a mknew or a create.
2092 ****************************************************************************/
2094 void reply_mknew(struct smb_request *req)
2096 connection_struct *conn = req->conn;
2097 struct smb_filename *smb_fname = NULL;
2100 struct smb_file_time ft;
2102 int oplock_request = 0;
2104 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2105 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2106 uint32 create_disposition;
2107 uint32 create_options = 0;
2108 TALLOC_CTX *ctx = talloc_tos();
2110 START_PROFILE(SMBcreate);
2114 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2118 fattr = SVAL(req->vwv+0, 0);
2119 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2122 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2124 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2125 STR_TERMINATE, &status);
2126 if (!NT_STATUS_IS_OK(status)) {
2127 reply_nterror(req, status);
2131 status = filename_convert(ctx,
2133 req->flags2 & FLAGS2_DFS_PATHNAMES,
2138 if (!NT_STATUS_IS_OK(status)) {
2139 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2140 reply_botherror(req,
2141 NT_STATUS_PATH_NOT_COVERED,
2142 ERRSRV, ERRbadpath);
2145 reply_nterror(req, status);
2149 if (fattr & aVOLID) {
2150 DEBUG(0,("Attempt to create file (%s) with volid set - "
2151 "please report this\n",
2152 smb_fname_str_dbg(smb_fname)));
2155 if(req->cmd == SMBmknew) {
2156 /* We should fail if file exists. */
2157 create_disposition = FILE_CREATE;
2159 /* Create if file doesn't exist, truncate if it does. */
2160 create_disposition = FILE_OVERWRITE_IF;
2163 status = SMB_VFS_CREATE_FILE(
2166 0, /* root_dir_fid */
2167 smb_fname, /* fname */
2168 access_mask, /* access_mask */
2169 share_mode, /* share_access */
2170 create_disposition, /* create_disposition*/
2171 create_options, /* create_options */
2172 fattr, /* file_attributes */
2173 oplock_request, /* oplock_request */
2174 0, /* allocation_size */
2175 0, /* private_flags */
2181 if (!NT_STATUS_IS_OK(status)) {
2182 if (open_was_deferred(req->mid)) {
2183 /* We have re-scheduled this call. */
2186 reply_openerror(req, status);
2190 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2191 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2192 if (!NT_STATUS_IS_OK(status)) {
2193 END_PROFILE(SMBcreate);
2197 reply_outbuf(req, 1, 0);
2198 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2200 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2201 SCVAL(req->outbuf,smb_flg,
2202 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2205 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2206 SCVAL(req->outbuf,smb_flg,
2207 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2210 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2211 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2212 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2213 (unsigned int)fattr));
2216 TALLOC_FREE(smb_fname);
2217 END_PROFILE(SMBcreate);
2221 /****************************************************************************
2222 Reply to a create temporary file.
2223 ****************************************************************************/
2225 void reply_ctemp(struct smb_request *req)
2227 connection_struct *conn = req->conn;
2228 struct smb_filename *smb_fname = NULL;
2236 TALLOC_CTX *ctx = talloc_tos();
2238 START_PROFILE(SMBctemp);
2241 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2245 fattr = SVAL(req->vwv+0, 0);
2246 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2248 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2249 STR_TERMINATE, &status);
2250 if (!NT_STATUS_IS_OK(status)) {
2251 reply_nterror(req, status);
2255 fname = talloc_asprintf(ctx,
2259 fname = talloc_strdup(ctx, "TMXXXXXX");
2263 reply_nterror(req, NT_STATUS_NO_MEMORY);
2267 status = filename_convert(ctx, conn,
2268 req->flags2 & FLAGS2_DFS_PATHNAMES,
2273 if (!NT_STATUS_IS_OK(status)) {
2274 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2275 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2276 ERRSRV, ERRbadpath);
2279 reply_nterror(req, status);
2283 tmpfd = mkstemp(smb_fname->base_name);
2285 reply_nterror(req, map_nt_error_from_unix(errno));
2289 SMB_VFS_STAT(conn, smb_fname);
2291 /* We should fail if file does not exist. */
2292 status = SMB_VFS_CREATE_FILE(
2295 0, /* root_dir_fid */
2296 smb_fname, /* fname */
2297 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2298 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2299 FILE_OPEN, /* create_disposition*/
2300 0, /* create_options */
2301 fattr, /* file_attributes */
2302 oplock_request, /* oplock_request */
2303 0, /* allocation_size */
2304 0, /* private_flags */
2310 /* close fd from mkstemp() */
2313 if (!NT_STATUS_IS_OK(status)) {
2314 if (open_was_deferred(req->mid)) {
2315 /* We have re-scheduled this call. */
2318 reply_openerror(req, status);
2322 reply_outbuf(req, 1, 0);
2323 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2325 /* the returned filename is relative to the directory */
2326 s = strrchr_m(fsp->fsp_name->base_name, '/');
2328 s = fsp->fsp_name->base_name;
2334 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2335 thing in the byte section. JRA */
2336 SSVALS(p, 0, -1); /* what is this? not in spec */
2338 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2340 reply_nterror(req, NT_STATUS_NO_MEMORY);
2344 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2345 SCVAL(req->outbuf, smb_flg,
2346 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2349 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2350 SCVAL(req->outbuf, smb_flg,
2351 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2354 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2355 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2356 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2358 TALLOC_FREE(smb_fname);
2359 END_PROFILE(SMBctemp);
2363 /*******************************************************************
2364 Check if a user is allowed to rename a file.
2365 ********************************************************************/
2367 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2372 if (!CAN_WRITE(conn)) {
2373 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2376 fmode = dos_mode(conn, fsp->fsp_name);
2377 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2378 return NT_STATUS_NO_SUCH_FILE;
2381 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2382 if (fsp->posix_open) {
2383 return NT_STATUS_OK;
2386 /* If no pathnames are open below this
2387 directory, allow the rename. */
2389 if (file_find_subpath(fsp)) {
2390 return NT_STATUS_ACCESS_DENIED;
2392 return NT_STATUS_OK;
2395 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2396 return NT_STATUS_OK;
2399 return NT_STATUS_ACCESS_DENIED;
2402 /*******************************************************************
2403 * unlink a file with all relevant access checks
2404 *******************************************************************/
2406 static NTSTATUS do_unlink(connection_struct *conn,
2407 struct smb_request *req,
2408 struct smb_filename *smb_fname,
2413 uint32 dirtype_orig = dirtype;
2416 bool posix_paths = lp_posix_pathnames();
2418 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2419 smb_fname_str_dbg(smb_fname),
2422 if (!CAN_WRITE(conn)) {
2423 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2427 ret = SMB_VFS_LSTAT(conn, smb_fname);
2429 ret = SMB_VFS_STAT(conn, smb_fname);
2432 return map_nt_error_from_unix(errno);
2435 fattr = dos_mode(conn, smb_fname);
2437 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2438 dirtype = aDIR|aARCH|aRONLY;
2441 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2443 return NT_STATUS_NO_SUCH_FILE;
2446 if (!dir_check_ftype(conn, fattr, dirtype)) {
2448 return NT_STATUS_FILE_IS_A_DIRECTORY;
2450 return NT_STATUS_NO_SUCH_FILE;
2453 if (dirtype_orig & 0x8000) {
2454 /* These will never be set for POSIX. */
2455 return NT_STATUS_NO_SUCH_FILE;
2459 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2460 return NT_STATUS_FILE_IS_A_DIRECTORY;
2463 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2464 return NT_STATUS_NO_SUCH_FILE;
2467 if (dirtype & 0xFF00) {
2468 /* These will never be set for POSIX. */
2469 return NT_STATUS_NO_SUCH_FILE;
2474 return NT_STATUS_NO_SUCH_FILE;
2477 /* Can't delete a directory. */
2479 return NT_STATUS_FILE_IS_A_DIRECTORY;
2484 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2485 return NT_STATUS_OBJECT_NAME_INVALID;
2486 #endif /* JRATEST */
2488 /* On open checks the open itself will check the share mode, so
2489 don't do it here as we'll get it wrong. */
2491 status = SMB_VFS_CREATE_FILE
2494 0, /* root_dir_fid */
2495 smb_fname, /* fname */
2496 DELETE_ACCESS, /* access_mask */
2497 FILE_SHARE_NONE, /* share_access */
2498 FILE_OPEN, /* create_disposition*/
2499 FILE_NON_DIRECTORY_FILE, /* create_options */
2500 /* file_attributes */
2501 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2502 FILE_ATTRIBUTE_NORMAL,
2503 0, /* oplock_request */
2504 0, /* allocation_size */
2505 0, /* private_flags */
2511 if (!NT_STATUS_IS_OK(status)) {
2512 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2513 nt_errstr(status)));
2517 status = can_set_delete_on_close(fsp, fattr);
2518 if (!NT_STATUS_IS_OK(status)) {
2519 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2521 smb_fname_str_dbg(smb_fname),
2522 nt_errstr(status)));
2523 close_file(req, fsp, NORMAL_CLOSE);
2527 /* The set is across all open files on this dev/inode pair. */
2528 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2529 close_file(req, fsp, NORMAL_CLOSE);
2530 return NT_STATUS_ACCESS_DENIED;
2533 return close_file(req, fsp, NORMAL_CLOSE);
2536 /****************************************************************************
2537 The guts of the unlink command, split out so it may be called by the NT SMB
2539 ****************************************************************************/
2541 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2542 uint32 dirtype, struct smb_filename *smb_fname,
2545 char *fname_dir = NULL;
2546 char *fname_mask = NULL;
2548 NTSTATUS status = NT_STATUS_OK;
2549 TALLOC_CTX *ctx = talloc_tos();
2551 /* Split up the directory from the filename/mask. */
2552 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2553 &fname_dir, &fname_mask);
2554 if (!NT_STATUS_IS_OK(status)) {
2559 * We should only check the mangled cache
2560 * here if unix_convert failed. This means
2561 * that the path in 'mask' doesn't exist
2562 * on the file system and so we need to look
2563 * for a possible mangle. This patch from
2564 * Tine Smukavec <valentin.smukavec@hermes.si>.
2567 if (!VALID_STAT(smb_fname->st) &&
2568 mangle_is_mangled(fname_mask, conn->params)) {
2569 char *new_mask = NULL;
2570 mangle_lookup_name_from_8_3(ctx, fname_mask,
2571 &new_mask, conn->params);
2573 TALLOC_FREE(fname_mask);
2574 fname_mask = new_mask;
2581 * Only one file needs to be unlinked. Append the mask back
2582 * onto the directory.
2584 TALLOC_FREE(smb_fname->base_name);
2585 smb_fname->base_name = talloc_asprintf(smb_fname,
2589 if (!smb_fname->base_name) {
2590 status = NT_STATUS_NO_MEMORY;
2594 dirtype = FILE_ATTRIBUTE_NORMAL;
2597 status = check_name(conn, smb_fname->base_name);
2598 if (!NT_STATUS_IS_OK(status)) {
2602 status = do_unlink(conn, req, smb_fname, dirtype);
2603 if (!NT_STATUS_IS_OK(status)) {
2609 struct smb_Dir *dir_hnd = NULL;
2611 const char *dname = NULL;
2612 char *talloced = NULL;
2614 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2615 status = NT_STATUS_OBJECT_NAME_INVALID;
2619 if (strequal(fname_mask,"????????.???")) {
2620 TALLOC_FREE(fname_mask);
2621 fname_mask = talloc_strdup(ctx, "*");
2623 status = NT_STATUS_NO_MEMORY;
2628 status = check_name(conn, fname_dir);
2629 if (!NT_STATUS_IS_OK(status)) {
2633 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2635 if (dir_hnd == NULL) {
2636 status = map_nt_error_from_unix(errno);
2640 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2641 the pattern matches against the long name, otherwise the short name
2642 We don't implement this yet XXXX
2645 status = NT_STATUS_NO_SUCH_FILE;
2647 while ((dname = ReadDirName(dir_hnd, &offset,
2648 &smb_fname->st, &talloced))) {
2649 TALLOC_CTX *frame = talloc_stackframe();
2651 if (!is_visible_file(conn, fname_dir, dname,
2652 &smb_fname->st, true)) {
2654 TALLOC_FREE(talloced);
2658 /* Quick check for "." and ".." */
2659 if (ISDOT(dname) || ISDOTDOT(dname)) {
2661 TALLOC_FREE(talloced);
2665 if(!mask_match(dname, fname_mask,
2666 conn->case_sensitive)) {
2668 TALLOC_FREE(talloced);
2672 TALLOC_FREE(smb_fname->base_name);
2673 smb_fname->base_name =
2674 talloc_asprintf(smb_fname, "%s/%s",
2677 if (!smb_fname->base_name) {
2678 TALLOC_FREE(dir_hnd);
2679 status = NT_STATUS_NO_MEMORY;
2681 TALLOC_FREE(talloced);
2685 status = check_name(conn, smb_fname->base_name);
2686 if (!NT_STATUS_IS_OK(status)) {
2687 TALLOC_FREE(dir_hnd);
2689 TALLOC_FREE(talloced);
2693 status = do_unlink(conn, req, smb_fname, dirtype);
2694 if (!NT_STATUS_IS_OK(status)) {
2696 TALLOC_FREE(talloced);
2701 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2702 smb_fname->base_name));
2705 TALLOC_FREE(talloced);
2707 TALLOC_FREE(dir_hnd);
2710 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2711 status = map_nt_error_from_unix(errno);
2715 TALLOC_FREE(fname_dir);
2716 TALLOC_FREE(fname_mask);
2720 /****************************************************************************
2722 ****************************************************************************/
2724 void reply_unlink(struct smb_request *req)
2726 connection_struct *conn = req->conn;
2728 struct smb_filename *smb_fname = NULL;
2731 bool path_contains_wcard = False;
2732 TALLOC_CTX *ctx = talloc_tos();
2734 START_PROFILE(SMBunlink);
2737 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2741 dirtype = SVAL(req->vwv+0, 0);
2743 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2744 STR_TERMINATE, &status,
2745 &path_contains_wcard);
2746 if (!NT_STATUS_IS_OK(status)) {
2747 reply_nterror(req, status);
2751 status = filename_convert(ctx, conn,
2752 req->flags2 & FLAGS2_DFS_PATHNAMES,
2754 UCF_COND_ALLOW_WCARD_LCOMP,
2755 &path_contains_wcard,
2757 if (!NT_STATUS_IS_OK(status)) {
2758 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2759 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2760 ERRSRV, ERRbadpath);
2763 reply_nterror(req, status);
2767 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2769 status = unlink_internals(conn, req, dirtype, smb_fname,
2770 path_contains_wcard);
2771 if (!NT_STATUS_IS_OK(status)) {
2772 if (open_was_deferred(req->mid)) {
2773 /* We have re-scheduled this call. */
2776 reply_nterror(req, status);
2780 reply_outbuf(req, 0, 0);
2782 TALLOC_FREE(smb_fname);
2783 END_PROFILE(SMBunlink);
2787 /****************************************************************************
2789 ****************************************************************************/
2791 static void fail_readraw(void)
2793 const char *errstr = talloc_asprintf(talloc_tos(),
2794 "FAIL ! reply_readbraw: socket write fail (%s)",
2799 exit_server_cleanly(errstr);
2802 /****************************************************************************
2803 Fake (read/write) sendfile. Returns -1 on read or write fail.
2804 ****************************************************************************/
2806 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2810 size_t tosend = nread;
2817 bufsize = MIN(nread, 65536);
2819 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2823 while (tosend > 0) {
2827 if (tosend > bufsize) {
2832 ret = read_file(fsp,buf,startpos,cur_read);
2838 /* If we had a short read, fill with zeros. */
2839 if (ret < cur_read) {
2840 memset(buf + ret, '\0', cur_read - ret);
2843 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2845 char addr[INET6_ADDRSTRLEN];
2847 * Try and give an error message saying what
2850 DEBUG(0, ("write_data failed for client %s. "
2852 get_peer_addr(fsp->conn->sconn->sock, addr,
2859 startpos += cur_read;
2863 return (ssize_t)nread;
2866 #if defined(WITH_SENDFILE)
2867 /****************************************************************************
2868 Deal with the case of sendfile reading less bytes from the file than
2869 requested. Fill with zeros (all we can do).
2870 ****************************************************************************/
2872 static void sendfile_short_send(files_struct *fsp,
2877 #define SHORT_SEND_BUFSIZE 1024
2878 if (nread < headersize) {
2879 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2880 "header for file %s (%s). Terminating\n",
2881 fsp_str_dbg(fsp), strerror(errno)));
2882 exit_server_cleanly("sendfile_short_send failed");
2885 nread -= headersize;
2887 if (nread < smb_maxcnt) {
2888 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2890 exit_server_cleanly("sendfile_short_send: "
2894 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2895 "with zeros !\n", fsp_str_dbg(fsp)));
2897 while (nread < smb_maxcnt) {
2899 * We asked for the real file size and told sendfile
2900 * to not go beyond the end of the file. But it can
2901 * happen that in between our fstat call and the
2902 * sendfile call the file was truncated. This is very
2903 * bad because we have already announced the larger
2904 * number of bytes to the client.
2906 * The best we can do now is to send 0-bytes, just as
2907 * a read from a hole in a sparse file would do.
2909 * This should happen rarely enough that I don't care
2910 * about efficiency here :-)
2914 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2915 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2917 char addr[INET6_ADDRSTRLEN];
2919 * Try and give an error message saying what
2922 DEBUG(0, ("write_data failed for client %s. "
2925 fsp->conn->sconn->sock, addr,
2928 exit_server_cleanly("sendfile_short_send: "
2929 "write_data failed");
2936 #endif /* defined WITH_SENDFILE */
2938 /****************************************************************************
2939 Return a readbraw error (4 bytes of zero).
2940 ****************************************************************************/
2942 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2948 smbd_lock_socket(sconn);
2949 if (write_data(sconn->sock,header,4) != 4) {
2950 char addr[INET6_ADDRSTRLEN];
2952 * Try and give an error message saying what
2955 DEBUG(0, ("write_data failed for client %s. "
2957 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2962 smbd_unlock_socket(sconn);
2965 /****************************************************************************
2966 Use sendfile in readbraw.
2967 ****************************************************************************/
2969 static void send_file_readbraw(connection_struct *conn,
2970 struct smb_request *req,
2976 struct smbd_server_connection *sconn = req->sconn;
2977 char *outbuf = NULL;
2980 #if defined(WITH_SENDFILE)
2982 * We can only use sendfile on a non-chained packet
2983 * but we can use on a non-oplocked file. tridge proved this
2984 * on a train in Germany :-). JRA.
2985 * reply_readbraw has already checked the length.
2988 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2989 (fsp->wcp == NULL) &&
2990 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
2991 ssize_t sendfile_read = -1;
2993 DATA_BLOB header_blob;
2995 _smb_setlen(header,nread);
2996 header_blob = data_blob_const(header, 4);
2998 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
2999 &header_blob, startpos,
3001 if (sendfile_read == -1) {
3002 /* Returning ENOSYS means no data at all was sent.
3003 * Do this as a normal read. */
3004 if (errno == ENOSYS) {
3005 goto normal_readbraw;
3009 * Special hack for broken Linux with no working sendfile. If we
3010 * return EINTR we sent the header but not the rest of the data.
3011 * Fake this up by doing read/write calls.
3013 if (errno == EINTR) {
3014 /* Ensure we don't do this again. */
3015 set_use_sendfile(SNUM(conn), False);
3016 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3018 if (fake_sendfile(fsp, startpos, nread) == -1) {
3019 DEBUG(0,("send_file_readbraw: "
3020 "fake_sendfile failed for "
3024 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3029 DEBUG(0,("send_file_readbraw: sendfile failed for "
3030 "file %s (%s). Terminating\n",
3031 fsp_str_dbg(fsp), strerror(errno)));
3032 exit_server_cleanly("send_file_readbraw sendfile failed");
3033 } else if (sendfile_read == 0) {
3035 * Some sendfile implementations return 0 to indicate
3036 * that there was a short read, but nothing was
3037 * actually written to the socket. In this case,
3038 * fallback to the normal read path so the header gets
3039 * the correct byte count.
3041 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3042 "bytes falling back to the normal read: "
3043 "%s\n", fsp_str_dbg(fsp)));
3044 goto normal_readbraw;
3047 /* Deal with possible short send. */
3048 if (sendfile_read != 4+nread) {
3049 sendfile_short_send(fsp, sendfile_read, 4, nread);
3057 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3059 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3060 (unsigned)(nread+4)));
3061 reply_readbraw_error(sconn);
3066 ret = read_file(fsp,outbuf+4,startpos,nread);
3067 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3076 _smb_setlen(outbuf,ret);
3077 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3078 char addr[INET6_ADDRSTRLEN];
3080 * Try and give an error message saying what
3083 DEBUG(0, ("write_data failed for client %s. "
3085 get_peer_addr(fsp->conn->sconn->sock, addr,
3092 TALLOC_FREE(outbuf);
3095 /****************************************************************************
3096 Reply to a readbraw (core+ protocol).
3097 ****************************************************************************/
3099 void reply_readbraw(struct smb_request *req)
3101 connection_struct *conn = req->conn;
3102 struct smbd_server_connection *sconn = req->sconn;
3103 ssize_t maxcount,mincount;
3107 struct lock_struct lock;
3110 START_PROFILE(SMBreadbraw);
3112 if (srv_is_signing_active(sconn) ||
3113 is_encrypted_packet(req->inbuf)) {
3114 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3115 "raw reads/writes are disallowed.");
3119 reply_readbraw_error(sconn);
3120 END_PROFILE(SMBreadbraw);
3124 if (sconn->smb1.echo_handler.trusted_fde) {
3125 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3126 "'async smb echo handler = yes'\n"));
3127 reply_readbraw_error(sconn);
3128 END_PROFILE(SMBreadbraw);
3133 * Special check if an oplock break has been issued
3134 * and the readraw request croses on the wire, we must
3135 * return a zero length response here.
3138 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3141 * We have to do a check_fsp by hand here, as
3142 * we must always return 4 zero bytes on error,
3146 if (!fsp || !conn || conn != fsp->conn ||
3147 req->vuid != fsp->vuid ||
3148 fsp->is_directory || fsp->fh->fd == -1) {
3150 * fsp could be NULL here so use the value from the packet. JRA.
3152 DEBUG(3,("reply_readbraw: fnum %d not valid "
3154 (int)SVAL(req->vwv+0, 0)));
3155 reply_readbraw_error(sconn);
3156 END_PROFILE(SMBreadbraw);
3160 /* Do a "by hand" version of CHECK_READ. */
3161 if (!(fsp->can_read ||
3162 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3163 (fsp->access_mask & FILE_EXECUTE)))) {
3164 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3165 (int)SVAL(req->vwv+0, 0)));
3166 reply_readbraw_error(sconn);
3167 END_PROFILE(SMBreadbraw);
3171 flush_write_cache(fsp, READRAW_FLUSH);
3173 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3174 if(req->wct == 10) {
3176 * This is a large offset (64 bit) read.
3178 #ifdef LARGE_SMB_OFF_T
3180 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3182 #else /* !LARGE_SMB_OFF_T */
3185 * Ensure we haven't been sent a >32 bit offset.
3188 if(IVAL(req->vwv+8, 0) != 0) {
3189 DEBUG(0,("reply_readbraw: large offset "
3190 "(%x << 32) used and we don't support "
3191 "64 bit offsets.\n",
3192 (unsigned int)IVAL(req->vwv+8, 0) ));
3193 reply_readbraw_error();
3194 END_PROFILE(SMBreadbraw);
3198 #endif /* LARGE_SMB_OFF_T */
3201 DEBUG(0,("reply_readbraw: negative 64 bit "
3202 "readraw offset (%.0f) !\n",
3203 (double)startpos ));
3204 reply_readbraw_error(sconn);
3205 END_PROFILE(SMBreadbraw);
3210 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3211 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3213 /* ensure we don't overrun the packet size */
3214 maxcount = MIN(65535,maxcount);
3216 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3217 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3220 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3221 reply_readbraw_error(sconn);
3222 END_PROFILE(SMBreadbraw);
3226 if (fsp_stat(fsp) == 0) {
3227 size = fsp->fsp_name->st.st_ex_size;
3230 if (startpos >= size) {
3233 nread = MIN(maxcount,(size - startpos));
3236 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3237 if (nread < mincount)
3241 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3242 "min=%lu nread=%lu\n",
3243 fsp->fnum, (double)startpos,
3244 (unsigned long)maxcount,
3245 (unsigned long)mincount,
3246 (unsigned long)nread ) );
3248 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3250 DEBUG(5,("reply_readbraw finished\n"));
3252 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3254 END_PROFILE(SMBreadbraw);
3259 #define DBGC_CLASS DBGC_LOCKING
3261 /****************************************************************************
3262 Reply to a lockread (core+ protocol).
3263 ****************************************************************************/
3265 void reply_lockread(struct smb_request *req)
3267 connection_struct *conn = req->conn;
3274 struct byte_range_lock *br_lck = NULL;
3276 struct smbd_server_connection *sconn = req->sconn;
3278 START_PROFILE(SMBlockread);
3281 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3282 END_PROFILE(SMBlockread);
3286 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3288 if (!check_fsp(conn, req, fsp)) {
3289 END_PROFILE(SMBlockread);
3293 if (!CHECK_READ(fsp,req)) {
3294 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3295 END_PROFILE(SMBlockread);
3299 numtoread = SVAL(req->vwv+1, 0);
3300 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3302 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3304 reply_outbuf(req, 5, numtoread + 3);
3306 data = smb_buf(req->outbuf) + 3;
3309 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3310 * protocol request that predates the read/write lock concept.
3311 * Thus instead of asking for a read lock here we need to ask
3312 * for a write lock. JRA.
3313 * Note that the requested lock size is unaffected by max_recv.
3316 br_lck = do_lock(req->sconn->msg_ctx,
3318 (uint64_t)req->smbpid,
3319 (uint64_t)numtoread,
3323 False, /* Non-blocking lock. */
3327 TALLOC_FREE(br_lck);
3329 if (NT_STATUS_V(status)) {
3330 reply_nterror(req, status);
3331 END_PROFILE(SMBlockread);
3336 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3339 if (numtoread > sconn->smb1.negprot.max_recv) {
3340 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3341 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3342 (unsigned int)numtoread,
3343 (unsigned int)sconn->smb1.negprot.max_recv));
3344 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3346 nread = read_file(fsp,data,startpos,numtoread);
3349 reply_nterror(req, map_nt_error_from_unix(errno));
3350 END_PROFILE(SMBlockread);
3354 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3356 SSVAL(req->outbuf,smb_vwv0,nread);
3357 SSVAL(req->outbuf,smb_vwv5,nread+3);
3358 p = smb_buf(req->outbuf);
3359 SCVAL(p,0,0); /* pad byte. */
3362 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3363 fsp->fnum, (int)numtoread, (int)nread));
3365 END_PROFILE(SMBlockread);
3370 #define DBGC_CLASS DBGC_ALL
3372 /****************************************************************************
3374 ****************************************************************************/
3376 void reply_read(struct smb_request *req)
3378 connection_struct *conn = req->conn;
3385 struct lock_struct lock;
3386 struct smbd_server_connection *sconn = req->sconn;
3388 START_PROFILE(SMBread);
3391 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3392 END_PROFILE(SMBread);
3396 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3398 if (!check_fsp(conn, req, fsp)) {
3399 END_PROFILE(SMBread);
3403 if (!CHECK_READ(fsp,req)) {
3404 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3405 END_PROFILE(SMBread);
3409 numtoread = SVAL(req->vwv+1, 0);
3410 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3412 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3415 * The requested read size cannot be greater than max_recv. JRA.
3417 if (numtoread > sconn->smb1.negprot.max_recv) {
3418 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3419 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3420 (unsigned int)numtoread,
3421 (unsigned int)sconn->smb1.negprot.max_recv));
3422 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3425 reply_outbuf(req, 5, numtoread+3);
3427 data = smb_buf(req->outbuf) + 3;
3429 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3430 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3433 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3434 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3435 END_PROFILE(SMBread);
3440 nread = read_file(fsp,data,startpos,numtoread);
3443 reply_nterror(req, map_nt_error_from_unix(errno));
3447 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3449 SSVAL(req->outbuf,smb_vwv0,nread);
3450 SSVAL(req->outbuf,smb_vwv5,nread+3);
3451 SCVAL(smb_buf(req->outbuf),0,1);
3452 SSVAL(smb_buf(req->outbuf),1,nread);
3454 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3455 fsp->fnum, (int)numtoread, (int)nread ) );
3458 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3460 END_PROFILE(SMBread);
3464 /****************************************************************************
3466 ****************************************************************************/
3468 static int setup_readX_header(struct smb_request *req, char *outbuf,
3474 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3475 data = smb_buf(outbuf);
3477 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3479 SCVAL(outbuf,smb_vwv0,0xFF);
3480 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3481 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3482 SSVAL(outbuf,smb_vwv6,
3484 + 1 /* the wct field */
3485 + 12 * sizeof(uint16_t) /* vwv */
3486 + 2); /* the buflen field */
3487 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3488 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3489 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3490 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3494 /****************************************************************************
3495 Reply to a read and X - possibly using sendfile.
3496 ****************************************************************************/
3498 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3499 files_struct *fsp, SMB_OFF_T startpos,
3503 struct lock_struct lock;
3504 int saved_errno = 0;
3506 if(fsp_stat(fsp) == -1) {
3507 reply_nterror(req, map_nt_error_from_unix(errno));
3511 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3512 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3515 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3516 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3520 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3521 (startpos > fsp->fsp_name->st.st_ex_size)
3522 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3524 * We already know that we would do a short read, so don't
3525 * try the sendfile() path.
3527 goto nosendfile_read;
3530 #if defined(WITH_SENDFILE)
3532 * We can only use sendfile on a non-chained packet
3533 * but we can use on a non-oplocked file. tridge proved this
3534 * on a train in Germany :-). JRA.
3537 if (!req_is_in_chain(req) &&
3538 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3539 (fsp->wcp == NULL) &&
3540 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3541 uint8 headerbuf[smb_size + 12 * 2];
3545 * Set up the packet header before send. We
3546 * assume here the sendfile will work (get the
3547 * correct amount of data).
3550 header = data_blob_const(headerbuf, sizeof(headerbuf));
3552 construct_reply_common_req(req, (char *)headerbuf);
3553 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3555 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3556 startpos, smb_maxcnt);
3558 /* Returning ENOSYS means no data at all was sent.
3559 Do this as a normal read. */
3560 if (errno == ENOSYS) {
3565 * Special hack for broken Linux with no working sendfile. If we
3566 * return EINTR we sent the header but not the rest of the data.
3567 * Fake this up by doing read/write calls.
3570 if (errno == EINTR) {
3571 /* Ensure we don't do this again. */
3572 set_use_sendfile(SNUM(conn), False);
3573 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3574 nread = fake_sendfile(fsp, startpos,
3577 DEBUG(0,("send_file_readX: "
3578 "fake_sendfile failed for "
3582 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3584 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3585 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3586 /* No outbuf here means successful sendfile. */
3590 DEBUG(0,("send_file_readX: sendfile failed for file "
3591 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3593 exit_server_cleanly("send_file_readX sendfile failed");
3594 } else if (nread == 0) {
3596 * Some sendfile implementations return 0 to indicate
3597 * that there was a short read, but nothing was
3598 * actually written to the socket. In this case,
3599 * fallback to the normal read path so the header gets
3600 * the correct byte count.
3602 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3603 "falling back to the normal read: %s\n",
3608 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3609 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3611 /* Deal with possible short send. */
3612 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3613 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3615 /* No outbuf here means successful sendfile. */
3616 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3617 SMB_PERFCOUNT_END(&req->pcd);
3625 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3626 uint8 headerbuf[smb_size + 2*12];
3628 construct_reply_common_req(req, (char *)headerbuf);
3629 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3631 /* Send out the header. */
3632 if (write_data(req->sconn->sock, (char *)headerbuf,
3633 sizeof(headerbuf)) != sizeof(headerbuf)) {
3635 char addr[INET6_ADDRSTRLEN];
3637 * Try and give an error message saying what
3640 DEBUG(0, ("write_data failed for client %s. "
3642 get_peer_addr(req->sconn->sock, addr,
3646 DEBUG(0,("send_file_readX: write_data failed for file "
3647 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3649 exit_server_cleanly("send_file_readX sendfile failed");
3651 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3653 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3654 "file %s (%s).\n", fsp_str_dbg(fsp),
3656 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3663 reply_outbuf(req, 12, smb_maxcnt);
3665 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3666 saved_errno = errno;
3668 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3671 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3675 setup_readX_header(req, (char *)req->outbuf, nread);
3677 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3678 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3684 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3685 TALLOC_FREE(req->outbuf);
3689 /****************************************************************************
3690 Reply to a read and X.
3691 ****************************************************************************/
3693 void reply_read_and_X(struct smb_request *req)
3695 connection_struct *conn = req->conn;
3699 bool big_readX = False;
3701 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3704 START_PROFILE(SMBreadX);
3706 if ((req->wct != 10) && (req->wct != 12)) {
3707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3711 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3712 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3713 smb_maxcnt = SVAL(req->vwv+5, 0);
3715 /* If it's an IPC, pass off the pipe handler. */
3717 reply_pipe_read_and_X(req);
3718 END_PROFILE(SMBreadX);
3722 if (!check_fsp(conn, req, fsp)) {
3723 END_PROFILE(SMBreadX);
3727 if (!CHECK_READ(fsp,req)) {
3728 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3729 END_PROFILE(SMBreadX);
3733 if (global_client_caps & CAP_LARGE_READX) {
3734 size_t upper_size = SVAL(req->vwv+7, 0);
3735 smb_maxcnt |= (upper_size<<16);
3736 if (upper_size > 1) {
3737 /* Can't do this on a chained packet. */
3738 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3739 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3740 END_PROFILE(SMBreadX);
3743 /* We currently don't do this on signed or sealed data. */
3744 if (srv_is_signing_active(req->sconn) ||
3745 is_encrypted_packet(req->inbuf)) {
3746 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3747 END_PROFILE(SMBreadX);
3750 /* Is there room in the reply for this data ? */
3751 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3753 NT_STATUS_INVALID_PARAMETER);
3754 END_PROFILE(SMBreadX);
3761 if (req->wct == 12) {
3762 #ifdef LARGE_SMB_OFF_T
3764 * This is a large offset (64 bit) read.
3766 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3768 #else /* !LARGE_SMB_OFF_T */
3771 * Ensure we haven't been sent a >32 bit offset.
3774 if(IVAL(req->vwv+10, 0) != 0) {
3775 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3776 "used and we don't support 64 bit offsets.\n",
3777 (unsigned int)IVAL(req->vwv+10, 0) ));
3778 END_PROFILE(SMBreadX);
3779 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3783 #endif /* LARGE_SMB_OFF_T */
3788 NTSTATUS status = schedule_aio_read_and_X(conn,
3793 if (NT_STATUS_IS_OK(status)) {
3794 /* Read scheduled - we're done. */
3797 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3798 /* Real error - report to client. */
3799 END_PROFILE(SMBreadX);
3800 reply_nterror(req, status);
3803 /* NT_STATUS_RETRY - fall back to sync read. */
3806 smbd_lock_socket(req->sconn);
3807 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3808 smbd_unlock_socket(req->sconn);
3811 END_PROFILE(SMBreadX);
3815 /****************************************************************************
3816 Error replies to writebraw must have smb_wct == 1. Fix this up.
3817 ****************************************************************************/
3819 void error_to_writebrawerr(struct smb_request *req)
3821 uint8 *old_outbuf = req->outbuf;
3823 reply_outbuf(req, 1, 0);
3825 memcpy(req->outbuf, old_outbuf, smb_size);
3826 TALLOC_FREE(old_outbuf);
3829 /****************************************************************************
3830 Read 4 bytes of a smb packet and return the smb length of the packet.
3831 Store the result in the buffer. This version of the function will
3832 never return a session keepalive (length of zero).
3833 Timeout is in milliseconds.
3834 ****************************************************************************/
3836 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3839 uint8_t msgtype = SMBkeepalive;
3841 while (msgtype == SMBkeepalive) {
3844 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3846 if (!NT_STATUS_IS_OK(status)) {
3847 char addr[INET6_ADDRSTRLEN];
3848 /* Try and give an error message
3849 * saying what client failed. */
3850 DEBUG(0, ("read_fd_with_timeout failed for "
3851 "client %s read error = %s.\n",
3852 get_peer_addr(fd,addr,sizeof(addr)),
3853 nt_errstr(status)));
3857 msgtype = CVAL(inbuf, 0);
3860 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3861 (unsigned long)len));
3863 return NT_STATUS_OK;
3866 /****************************************************************************
3867 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3868 ****************************************************************************/
3870 void reply_writebraw(struct smb_request *req)
3872 connection_struct *conn = req->conn;
3875 ssize_t total_written=0;
3876 size_t numtowrite=0;
3882 struct lock_struct lock;
3885 START_PROFILE(SMBwritebraw);
3888 * If we ever reply with an error, it must have the SMB command
3889 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3892 SCVAL(req->inbuf,smb_com,SMBwritec);
3894 if (srv_is_signing_active(req->sconn)) {
3895 END_PROFILE(SMBwritebraw);
3896 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3897 "raw reads/writes are disallowed.");
3900 if (req->wct < 12) {
3901 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3902 error_to_writebrawerr(req);
3903 END_PROFILE(SMBwritebraw);
3907 if (req->sconn->smb1.echo_handler.trusted_fde) {
3908 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3909 "'async smb echo handler = yes'\n"));
3910 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3911 error_to_writebrawerr(req);
3912 END_PROFILE(SMBwritebraw);
3916 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3917 if (!check_fsp(conn, req, fsp)) {
3918 error_to_writebrawerr(req);
3919 END_PROFILE(SMBwritebraw);
3923 if (!CHECK_WRITE(fsp)) {
3924 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3925 error_to_writebrawerr(req);
3926 END_PROFILE(SMBwritebraw);
3930 tcount = IVAL(req->vwv+1, 0);
3931 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3932 write_through = BITSETW(req->vwv+7,0);
3934 /* We have to deal with slightly different formats depending
3935 on whether we are using the core+ or lanman1.0 protocol */
3937 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3938 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3939 data = smb_buf(req->inbuf);
3941 numtowrite = SVAL(req->vwv+10, 0);
3942 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3945 /* Ensure we don't write bytes past the end of this packet. */
3946 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3948 error_to_writebrawerr(req);
3949 END_PROFILE(SMBwritebraw);
3953 if (!fsp->print_file) {
3954 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3955 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3958 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3959 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3960 error_to_writebrawerr(req);
3961 END_PROFILE(SMBwritebraw);
3967 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3970 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3971 "wrote=%d sync=%d\n",
3972 fsp->fnum, (double)startpos, (int)numtowrite,
3973 (int)nwritten, (int)write_through));
3975 if (nwritten < (ssize_t)numtowrite) {
3976 reply_nterror(req, NT_STATUS_DISK_FULL);
3977 error_to_writebrawerr(req);
3981 total_written = nwritten;
3983 /* Allocate a buffer of 64k + length. */
3984 buf = TALLOC_ARRAY(NULL, char, 65540);
3986 reply_nterror(req, NT_STATUS_NO_MEMORY);
3987 error_to_writebrawerr(req);
3991 /* Return a SMBwritebraw message to the redirector to tell
3992 * it to send more bytes */
3994 memcpy(buf, req->inbuf, smb_size);
3995 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3996 SCVAL(buf,smb_com,SMBwritebraw);
3997 SSVALS(buf,smb_vwv0,0xFFFF);
3999 if (!srv_send_smb(req->sconn,
4001 false, 0, /* no signing */
4002 IS_CONN_ENCRYPTED(conn),
4004 exit_server_cleanly("reply_writebraw: srv_send_smb "
4008 /* Now read the raw data into the buffer and write it */
4009 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4011 if (!NT_STATUS_IS_OK(status)) {
4012 exit_server_cleanly("secondary writebraw failed");
4015 /* Set up outbuf to return the correct size */
4016 reply_outbuf(req, 1, 0);
4018 if (numtowrite != 0) {
4020 if (numtowrite > 0xFFFF) {
4021 DEBUG(0,("reply_writebraw: Oversize secondary write "
4022 "raw requested (%u). Terminating\n",
4023 (unsigned int)numtowrite ));
4024 exit_server_cleanly("secondary writebraw failed");
4027 if (tcount > nwritten+numtowrite) {
4028 DEBUG(3,("reply_writebraw: Client overestimated the "
4030 (int)tcount,(int)nwritten,(int)numtowrite));
4033 status = read_data(req->sconn->sock, buf+4, numtowrite);
4035 if (!NT_STATUS_IS_OK(status)) {
4036 char addr[INET6_ADDRSTRLEN];
4037 /* Try and give an error message
4038 * saying what client failed. */
4039 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4040 "raw read failed (%s) for client %s. "
4041 "Terminating\n", nt_errstr(status),
4042 get_peer_addr(req->sconn->sock, addr,
4044 exit_server_cleanly("secondary writebraw failed");
4047 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4048 if (nwritten == -1) {
4050 reply_nterror(req, map_nt_error_from_unix(errno));
4051 error_to_writebrawerr(req);
4055 if (nwritten < (ssize_t)numtowrite) {
4056 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4057 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4061 total_written += nwritten;
4066 SSVAL(req->outbuf,smb_vwv0,total_written);
4068 status = sync_file(conn, fsp, write_through);
4069 if (!NT_STATUS_IS_OK(status)) {
4070 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4071 fsp_str_dbg(fsp), nt_errstr(status)));
4072 reply_nterror(req, status);
4073 error_to_writebrawerr(req);
4077 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4079 fsp->fnum, (double)startpos, (int)numtowrite,
4080 (int)total_written));
4082 if (!fsp->print_file) {
4083 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4086 /* We won't return a status if write through is not selected - this
4087 * follows what WfWg does */
4088 END_PROFILE(SMBwritebraw);
4090 if (!write_through && total_written==tcount) {
4092 #if RABBIT_PELLET_FIX
4094 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4095 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
4098 if (!send_keepalive(req->sconn->sock)) {
4099 exit_server_cleanly("reply_writebraw: send of "
4100 "keepalive failed");
4103 TALLOC_FREE(req->outbuf);
4108 if (!fsp->print_file) {
4109 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4112 END_PROFILE(SMBwritebraw);
4117 #define DBGC_CLASS DBGC_LOCKING
4119 /****************************************************************************
4120 Reply to a writeunlock (core+).
4121 ****************************************************************************/
4123 void reply_writeunlock(struct smb_request *req)
4125 connection_struct *conn = req->conn;
4126 ssize_t nwritten = -1;
4130 NTSTATUS status = NT_STATUS_OK;
4132 struct lock_struct lock;
4133 int saved_errno = 0;
4135 START_PROFILE(SMBwriteunlock);
4138 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4139 END_PROFILE(SMBwriteunlock);
4143 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4145 if (!check_fsp(conn, req, fsp)) {
4146 END_PROFILE(SMBwriteunlock);
4150 if (!CHECK_WRITE(fsp)) {
4151 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4152 END_PROFILE(SMBwriteunlock);
4156 numtowrite = SVAL(req->vwv+1, 0);
4157 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4158 data = (const char *)req->buf + 3;
4160 if (!fsp->print_file && numtowrite > 0) {
4161 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4162 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4165 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4166 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4167 END_PROFILE(SMBwriteunlock);
4172 /* The special X/Open SMB protocol handling of
4173 zero length writes is *NOT* done for
4175 if(numtowrite == 0) {
4178 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4179 saved_errno = errno;
4182 status = sync_file(conn, fsp, False /* write through */);
4183 if (!NT_STATUS_IS_OK(status)) {
4184 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4185 fsp_str_dbg(fsp), nt_errstr(status)));
4186 reply_nterror(req, status);
4191 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4195 if((nwritten < numtowrite) && (numtowrite != 0)) {
4196 reply_nterror(req, NT_STATUS_DISK_FULL);
4200 if (numtowrite && !fsp->print_file) {
4201 status = do_unlock(req->sconn->msg_ctx,
4203 (uint64_t)req->smbpid,
4204 (uint64_t)numtowrite,
4208 if (NT_STATUS_V(status)) {
4209 reply_nterror(req, status);
4214 reply_outbuf(req, 1, 0);
4216 SSVAL(req->outbuf,smb_vwv0,nwritten);
4218 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4219 fsp->fnum, (int)numtowrite, (int)nwritten));
4222 if (numtowrite && !fsp->print_file) {
4223 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4226 END_PROFILE(SMBwriteunlock);
4231 #define DBGC_CLASS DBGC_ALL
4233 /****************************************************************************
4235 ****************************************************************************/
4237 void reply_write(struct smb_request *req)
4239 connection_struct *conn = req->conn;
4241 ssize_t nwritten = -1;
4245 struct lock_struct lock;
4247 int saved_errno = 0;
4249 START_PROFILE(SMBwrite);
4252 END_PROFILE(SMBwrite);
4253 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4257 /* If it's an IPC, pass off the pipe handler. */
4259 reply_pipe_write(req);
4260 END_PROFILE(SMBwrite);
4264 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4266 if (!check_fsp(conn, req, fsp)) {
4267 END_PROFILE(SMBwrite);
4271 if (!CHECK_WRITE(fsp)) {
4272 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4273 END_PROFILE(SMBwrite);
4277 numtowrite = SVAL(req->vwv+1, 0);
4278 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4279 data = (const char *)req->buf + 3;
4281 if (!fsp->print_file) {
4282 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4283 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4286 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4287 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4288 END_PROFILE(SMBwrite);
4294 * X/Open SMB protocol says that if smb_vwv1 is
4295 * zero then the file size should be extended or
4296 * truncated to the size given in smb_vwv[2-3].
4299 if(numtowrite == 0) {
4301 * This is actually an allocate call, and set EOF. JRA.
4303 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4305 reply_nterror(req, NT_STATUS_DISK_FULL);
4308 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4310 reply_nterror(req, NT_STATUS_DISK_FULL);
4313 trigger_write_time_update_immediate(fsp);
4315 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4318 status = sync_file(conn, fsp, False);
4319 if (!NT_STATUS_IS_OK(status)) {
4320 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4321 fsp_str_dbg(fsp), nt_errstr(status)));
4322 reply_nterror(req, status);
4327 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4331 if((nwritten == 0) && (numtowrite != 0)) {
4332 reply_nterror(req, NT_STATUS_DISK_FULL);
4336 reply_outbuf(req, 1, 0);
4338 SSVAL(req->outbuf,smb_vwv0,nwritten);
4340 if (nwritten < (ssize_t)numtowrite) {
4341 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4342 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4345 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4348 if (!fsp->print_file) {
4349 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4352 END_PROFILE(SMBwrite);
4356 /****************************************************************************
4357 Ensure a buffer is a valid writeX for recvfile purposes.
4358 ****************************************************************************/
4360 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4361 (2*14) + /* word count (including bcc) */ \
4364 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4365 const uint8_t *inbuf)
4368 connection_struct *conn = NULL;
4369 unsigned int doff = 0;
4370 size_t len = smb_len_large(inbuf);
4372 if (is_encrypted_packet(inbuf)) {
4373 /* Can't do this on encrypted
4378 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4382 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4383 CVAL(inbuf,smb_wct) != 14) {
4384 DEBUG(10,("is_valid_writeX_buffer: chained or "
4385 "invalid word length.\n"));
4389 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4391 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4395 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4398 if (IS_PRINT(conn)) {
4399 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4402 doff = SVAL(inbuf,smb_vwv11);
4404 numtowrite = SVAL(inbuf,smb_vwv10);
4406 if (len > doff && len - doff > 0xFFFF) {
4407 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4410 if (numtowrite == 0) {
4411 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4415 /* Ensure the sizes match up. */
4416 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4417 /* no pad byte...old smbclient :-( */
4418 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4420 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4424 if (len - doff != numtowrite) {
4425 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4426 "len = %u, doff = %u, numtowrite = %u\n",
4429 (unsigned int)numtowrite ));
4433 DEBUG(10,("is_valid_writeX_buffer: true "
4434 "len = %u, doff = %u, numtowrite = %u\n",
4437 (unsigned int)numtowrite ));
4442 /****************************************************************************
4443 Reply to a write and X.
4444 ****************************************************************************/
4446 void reply_write_and_X(struct smb_request *req)
4448 connection_struct *conn = req->conn;
4450 struct lock_struct lock;
4455 unsigned int smb_doff;
4456 unsigned int smblen;
4459 int saved_errno = 0;
4461 START_PROFILE(SMBwriteX);
4463 if ((req->wct != 12) && (req->wct != 14)) {
4464 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4465 END_PROFILE(SMBwriteX);
4469 numtowrite = SVAL(req->vwv+10, 0);
4470 smb_doff = SVAL(req->vwv+11, 0);
4471 smblen = smb_len(req->inbuf);
4473 if (req->unread_bytes > 0xFFFF ||
4474 (smblen > smb_doff &&
4475 smblen - smb_doff > 0xFFFF)) {
4476 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4479 if (req->unread_bytes) {
4480 /* Can't do a recvfile write on IPC$ */
4482 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4483 END_PROFILE(SMBwriteX);
4486 if (numtowrite != req->unread_bytes) {
4487 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4488 END_PROFILE(SMBwriteX);
4492 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4493 smb_doff + numtowrite > smblen) {
4494 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4495 END_PROFILE(SMBwriteX);
4500 /* If it's an IPC, pass off the pipe handler. */
4502 if (req->unread_bytes) {
4503 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4504 END_PROFILE(SMBwriteX);
4507 reply_pipe_write_and_X(req);
4508 END_PROFILE(SMBwriteX);
4512 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4513 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4514 write_through = BITSETW(req->vwv+7,0);
4516 if (!check_fsp(conn, req, fsp)) {
4517 END_PROFILE(SMBwriteX);
4521 if (!CHECK_WRITE(fsp)) {
4522 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4523 END_PROFILE(SMBwriteX);
4527 data = smb_base(req->inbuf) + smb_doff;
4529 if(req->wct == 14) {
4530 #ifdef LARGE_SMB_OFF_T
4532 * This is a large offset (64 bit) write.
4534 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4536 #else /* !LARGE_SMB_OFF_T */
4539 * Ensure we haven't been sent a >32 bit offset.
4542 if(IVAL(req->vwv+12, 0) != 0) {
4543 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4544 "used and we don't support 64 bit offsets.\n",
4545 (unsigned int)IVAL(req->vwv+12, 0) ));
4546 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4547 END_PROFILE(SMBwriteX);
4551 #endif /* LARGE_SMB_OFF_T */
4554 /* X/Open SMB protocol says that, unlike SMBwrite
4555 if the length is zero then NO truncation is
4556 done, just a write of zero. To truncate a file,
4559 if(numtowrite == 0) {
4562 if (req->unread_bytes == 0) {
4563 status = schedule_aio_write_and_X(conn,
4570 if (NT_STATUS_IS_OK(status)) {
4571 /* write scheduled - we're done. */
4574 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4575 /* Real error - report to client. */
4576 reply_nterror(req, status);
4579 /* NT_STATUS_RETRY - fall through to sync write. */
4582 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4583 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4586 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4587 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4591 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4592 saved_errno = errno;
4594 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4598 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4602 if((nwritten == 0) && (numtowrite != 0)) {
4603 reply_nterror(req, NT_STATUS_DISK_FULL);
4607 reply_outbuf(req, 6, 0);
4608 SSVAL(req->outbuf,smb_vwv2,nwritten);
4609 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4611 if (nwritten < (ssize_t)numtowrite) {
4612 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4613 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4616 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4617 fsp->fnum, (int)numtowrite, (int)nwritten));
4619 status = sync_file(conn, fsp, write_through);
4620 if (!NT_STATUS_IS_OK(status)) {
4621 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4622 fsp_str_dbg(fsp), nt_errstr(status)));
4623 reply_nterror(req, status);
4627 END_PROFILE(SMBwriteX);
4632 END_PROFILE(SMBwriteX);
4636 /****************************************************************************
4638 ****************************************************************************/
4640 void reply_lseek(struct smb_request *req)
4642 connection_struct *conn = req->conn;
4648 START_PROFILE(SMBlseek);
4651 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4652 END_PROFILE(SMBlseek);
4656 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4658 if (!check_fsp(conn, req, fsp)) {
4662 flush_write_cache(fsp, SEEK_FLUSH);
4664 mode = SVAL(req->vwv+1, 0) & 3;
4665 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4666 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4675 res = fsp->fh->pos + startpos;
4686 if (umode == SEEK_END) {
4687 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4688 if(errno == EINVAL) {
4689 SMB_OFF_T current_pos = startpos;
4691 if(fsp_stat(fsp) == -1) {
4693 map_nt_error_from_unix(errno));
4694 END_PROFILE(SMBlseek);
4698 current_pos += fsp->fsp_name->st.st_ex_size;
4700 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4705 reply_nterror(req, map_nt_error_from_unix(errno));
4706 END_PROFILE(SMBlseek);
4713 reply_outbuf(req, 2, 0);
4714 SIVAL(req->outbuf,smb_vwv0,res);
4716 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4717 fsp->fnum, (double)startpos, (double)res, mode));
4719 END_PROFILE(SMBlseek);
4723 /****************************************************************************
4725 ****************************************************************************/
4727 void reply_flush(struct smb_request *req)
4729 connection_struct *conn = req->conn;
4733 START_PROFILE(SMBflush);
4736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4740 fnum = SVAL(req->vwv+0, 0);
4741 fsp = file_fsp(req, fnum);
4743 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4748 file_sync_all(conn);
4750 NTSTATUS status = sync_file(conn, fsp, True);
4751 if (!NT_STATUS_IS_OK(status)) {
4752 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4753 fsp_str_dbg(fsp), nt_errstr(status)));
4754 reply_nterror(req, status);
4755 END_PROFILE(SMBflush);
4760 reply_outbuf(req, 0, 0);
4762 DEBUG(3,("flush\n"));
4763 END_PROFILE(SMBflush);
4767 /****************************************************************************
4769 conn POINTER CAN BE NULL HERE !
4770 ****************************************************************************/
4772 void reply_exit(struct smb_request *req)
4774 START_PROFILE(SMBexit);
4776 file_close_pid(req->smbpid, req->vuid);
4778 reply_outbuf(req, 0, 0);
4780 DEBUG(3,("exit\n"));
4782 END_PROFILE(SMBexit);
4786 /****************************************************************************
4787 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4788 ****************************************************************************/
4790 void reply_close(struct smb_request *req)
4792 connection_struct *conn = req->conn;
4793 NTSTATUS status = NT_STATUS_OK;
4794 files_struct *fsp = NULL;
4795 START_PROFILE(SMBclose);
4798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4799 END_PROFILE(SMBclose);
4803 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4806 * We can only use check_fsp if we know it's not a directory.
4809 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4810 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4811 END_PROFILE(SMBclose);
4815 if(fsp->is_directory) {
4817 * Special case - close NT SMB directory handle.
4819 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4820 status = close_file(req, fsp, NORMAL_CLOSE);
4824 * Close ordinary file.
4827 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4828 fsp->fh->fd, fsp->fnum,
4829 conn->num_files_open));
4832 * Take care of any time sent in the close.
4835 t = srv_make_unix_date3(req->vwv+1);
4836 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4839 * close_file() returns the unix errno if an error
4840 * was detected on close - normally this is due to
4841 * a disk full error. If not then it was probably an I/O error.
4844 status = close_file(req, fsp, NORMAL_CLOSE);
4847 if (!NT_STATUS_IS_OK(status)) {
4848 reply_nterror(req, status);
4849 END_PROFILE(SMBclose);
4853 reply_outbuf(req, 0, 0);
4854 END_PROFILE(SMBclose);
4858 /****************************************************************************
4859 Reply to a writeclose (Core+ protocol).
4860 ****************************************************************************/
4862 void reply_writeclose(struct smb_request *req)
4864 connection_struct *conn = req->conn;
4866 ssize_t nwritten = -1;
4867 NTSTATUS close_status = NT_STATUS_OK;
4870 struct timespec mtime;
4872 struct lock_struct lock;
4874 START_PROFILE(SMBwriteclose);
4877 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4878 END_PROFILE(SMBwriteclose);
4882 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4884 if (!check_fsp(conn, req, fsp)) {
4885 END_PROFILE(SMBwriteclose);
4888 if (!CHECK_WRITE(fsp)) {
4889 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4890 END_PROFILE(SMBwriteclose);
4894 numtowrite = SVAL(req->vwv+1, 0);
4895 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4896 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4897 data = (const char *)req->buf + 1;
4899 if (!fsp->print_file) {
4900 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4901 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4904 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4905 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4906 END_PROFILE(SMBwriteclose);
4911 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4913 set_close_write_time(fsp, mtime);
4916 * More insanity. W2K only closes the file if writelen > 0.
4921 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4922 "file %s\n", fsp_str_dbg(fsp)));
4923 close_status = close_file(req, fsp, NORMAL_CLOSE);
4926 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4927 fsp->fnum, (int)numtowrite, (int)nwritten,
4928 conn->num_files_open));
4930 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4931 reply_nterror(req, NT_STATUS_DISK_FULL);
4935 if(!NT_STATUS_IS_OK(close_status)) {
4936 reply_nterror(req, close_status);
4940 reply_outbuf(req, 1, 0);
4942 SSVAL(req->outbuf,smb_vwv0,nwritten);
4945 if (numtowrite && !fsp->print_file) {
4946 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4949 END_PROFILE(SMBwriteclose);
4954 #define DBGC_CLASS DBGC_LOCKING
4956 /****************************************************************************
4958 ****************************************************************************/
4960 void reply_lock(struct smb_request *req)
4962 connection_struct *conn = req->conn;
4963 uint64_t count,offset;
4966 struct byte_range_lock *br_lck = NULL;
4968 START_PROFILE(SMBlock);
4971 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4972 END_PROFILE(SMBlock);
4976 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4978 if (!check_fsp(conn, req, fsp)) {
4979 END_PROFILE(SMBlock);
4983 count = (uint64_t)IVAL(req->vwv+1, 0);
4984 offset = (uint64_t)IVAL(req->vwv+3, 0);
4986 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4987 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4989 br_lck = do_lock(req->sconn->msg_ctx,
4991 (uint64_t)req->smbpid,
4996 False, /* Non-blocking lock. */
5001 TALLOC_FREE(br_lck);
5003 if (NT_STATUS_V(status)) {
5004 reply_nterror(req, status);
5005 END_PROFILE(SMBlock);
5009 reply_outbuf(req, 0, 0);
5011 END_PROFILE(SMBlock);
5015 /****************************************************************************
5017 ****************************************************************************/
5019 void reply_unlock(struct smb_request *req)
5021 connection_struct *conn = req->conn;
5022 uint64_t count,offset;
5026 START_PROFILE(SMBunlock);
5029 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5030 END_PROFILE(SMBunlock);
5034 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5036 if (!check_fsp(conn, req, fsp)) {
5037 END_PROFILE(SMBunlock);
5041 count = (uint64_t)IVAL(req->vwv+1, 0);
5042 offset = (uint64_t)IVAL(req->vwv+3, 0);
5044 status = do_unlock(req->sconn->msg_ctx,
5046 (uint64_t)req->smbpid,
5051 if (NT_STATUS_V(status)) {
5052 reply_nterror(req, status);
5053 END_PROFILE(SMBunlock);
5057 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5058 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5060 reply_outbuf(req, 0, 0);
5062 END_PROFILE(SMBunlock);
5067 #define DBGC_CLASS DBGC_ALL
5069 /****************************************************************************
5071 conn POINTER CAN BE NULL HERE !
5072 ****************************************************************************/
5074 void reply_tdis(struct smb_request *req)
5076 connection_struct *conn = req->conn;
5077 START_PROFILE(SMBtdis);
5080 DEBUG(4,("Invalid connection in tdis\n"));
5081 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5082 END_PROFILE(SMBtdis);
5088 close_cnum(conn,req->vuid);
5091 reply_outbuf(req, 0, 0);
5092 END_PROFILE(SMBtdis);
5096 /****************************************************************************
5098 conn POINTER CAN BE NULL HERE !
5099 ****************************************************************************/
5101 void reply_echo(struct smb_request *req)
5103 connection_struct *conn = req->conn;
5104 struct smb_perfcount_data local_pcd;
5105 struct smb_perfcount_data *cur_pcd;
5109 START_PROFILE(SMBecho);
5111 smb_init_perfcount_data(&local_pcd);
5114 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5115 END_PROFILE(SMBecho);
5119 smb_reverb = SVAL(req->vwv+0, 0);
5121 reply_outbuf(req, 1, req->buflen);
5123 /* copy any incoming data back out */
5124 if (req->buflen > 0) {
5125 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5128 if (smb_reverb > 100) {
5129 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5133 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5135 /* this makes sure we catch the request pcd */
5136 if (seq_num == smb_reverb) {
5137 cur_pcd = &req->pcd;
5139 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5140 cur_pcd = &local_pcd;
5143 SSVAL(req->outbuf,smb_vwv0,seq_num);
5145 show_msg((char *)req->outbuf);
5146 if (!srv_send_smb(req->sconn,
5147 (char *)req->outbuf,
5148 true, req->seqnum+1,
5149 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5151 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5154 DEBUG(3,("echo %d times\n", smb_reverb));
5156 TALLOC_FREE(req->outbuf);
5158 END_PROFILE(SMBecho);
5162 /****************************************************************************
5163 Reply to a printopen.
5164 ****************************************************************************/
5166 void reply_printopen(struct smb_request *req)
5168 connection_struct *conn = req->conn;
5172 START_PROFILE(SMBsplopen);
5175 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5176 END_PROFILE(SMBsplopen);
5180 if (!CAN_PRINT(conn)) {
5181 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5182 END_PROFILE(SMBsplopen);
5186 status = file_new(req, conn, &fsp);
5187 if(!NT_STATUS_IS_OK(status)) {
5188 reply_nterror(req, status);
5189 END_PROFILE(SMBsplopen);
5193 /* Open for exclusive use, write only. */
5194 status = print_spool_open(fsp, NULL, req->vuid);
5196 if (!NT_STATUS_IS_OK(status)) {
5197 file_free(req, fsp);
5198 reply_nterror(req, status);
5199 END_PROFILE(SMBsplopen);
5203 reply_outbuf(req, 1, 0);
5204 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5206 DEBUG(3,("openprint fd=%d fnum=%d\n",
5207 fsp->fh->fd, fsp->fnum));
5209 END_PROFILE(SMBsplopen);
5213 /****************************************************************************
5214 Reply to a printclose.
5215 ****************************************************************************/
5217 void reply_printclose(struct smb_request *req)
5219 connection_struct *conn = req->conn;
5223 START_PROFILE(SMBsplclose);
5226 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5227 END_PROFILE(SMBsplclose);
5231 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5233 if (!check_fsp(conn, req, fsp)) {
5234 END_PROFILE(SMBsplclose);
5238 if (!CAN_PRINT(conn)) {
5239 reply_force_doserror(req, ERRSRV, ERRerror);
5240 END_PROFILE(SMBsplclose);
5244 DEBUG(3,("printclose fd=%d fnum=%d\n",
5245 fsp->fh->fd,fsp->fnum));
5247 status = close_file(req, fsp, NORMAL_CLOSE);
5249 if(!NT_STATUS_IS_OK(status)) {
5250 reply_nterror(req, status);
5251 END_PROFILE(SMBsplclose);
5255 reply_outbuf(req, 0, 0);
5257 END_PROFILE(SMBsplclose);
5261 /****************************************************************************
5262 Reply to a printqueue.
5263 ****************************************************************************/
5265 void reply_printqueue(struct smb_request *req)
5267 connection_struct *conn = req->conn;
5271 START_PROFILE(SMBsplretq);
5274 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5275 END_PROFILE(SMBsplretq);
5279 max_count = SVAL(req->vwv+0, 0);
5280 start_index = SVAL(req->vwv+1, 0);
5282 /* we used to allow the client to get the cnum wrong, but that
5283 is really quite gross and only worked when there was only
5284 one printer - I think we should now only accept it if they
5285 get it right (tridge) */
5286 if (!CAN_PRINT(conn)) {
5287 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5288 END_PROFILE(SMBsplretq);
5292 reply_outbuf(req, 2, 3);
5293 SSVAL(req->outbuf,smb_vwv0,0);
5294 SSVAL(req->outbuf,smb_vwv1,0);
5295 SCVAL(smb_buf(req->outbuf),0,1);
5296 SSVAL(smb_buf(req->outbuf),1,0);
5298 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5299 start_index, max_count));
5302 TALLOC_CTX *mem_ctx = talloc_tos();
5305 const char *sharename = lp_servicename(SNUM(conn));
5306 struct rpc_pipe_client *cli = NULL;
5307 struct policy_handle handle;
5308 struct spoolss_DevmodeContainer devmode_ctr;
5309 union spoolss_JobInfo *info;
5311 uint32_t num_to_get;
5315 ZERO_STRUCT(handle);
5317 status = rpc_pipe_open_interface(conn,
5318 &ndr_table_spoolss.syntax_id,
5320 &conn->sconn->client_id,
5321 conn->sconn->msg_ctx,
5323 if (!NT_STATUS_IS_OK(status)) {
5324 DEBUG(0, ("reply_printqueue: "
5325 "could not connect to spoolss: %s\n",
5326 nt_errstr(status)));
5327 reply_nterror(req, status);
5331 ZERO_STRUCT(devmode_ctr);
5333 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
5336 SEC_FLAG_MAXIMUM_ALLOWED,
5339 if (!NT_STATUS_IS_OK(status)) {
5340 reply_nterror(req, status);
5343 if (!W_ERROR_IS_OK(werr)) {
5344 reply_nterror(req, werror_to_ntstatus(werr));
5348 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5356 if (!W_ERROR_IS_OK(werr)) {
5357 reply_nterror(req, werror_to_ntstatus(werr));
5361 if (max_count > 0) {
5362 first = start_index;
5364 first = start_index + max_count + 1;
5367 if (first >= count) {
5370 num_to_get = first + MIN(ABS(max_count), count - first);
5373 for (i = first; i < num_to_get; i++) {
5376 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5378 uint16_t qrapjobid = pjobid_to_rap(sharename,
5379 info[i].info2.job_id);
5381 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5387 srv_put_dos_date2(p, 0, qtime);
5388 SCVAL(p, 4, qstatus);
5389 SSVAL(p, 5, qrapjobid);
5390 SIVAL(p, 7, info[i].info2.size);
5392 srvstr_push(blob, req->flags2, p+12,
5393 info[i].info2.notify_name, 16, STR_ASCII);
5395 if (message_push_blob(
5398 blob, sizeof(blob))) == -1) {
5399 reply_nterror(req, NT_STATUS_NO_MEMORY);
5405 SSVAL(req->outbuf,smb_vwv0,count);
5406 SSVAL(req->outbuf,smb_vwv1,
5407 (max_count>0?first+count:first-1));
5408 SCVAL(smb_buf(req->outbuf),0,1);
5409 SSVAL(smb_buf(req->outbuf),1,28*count);
5413 DEBUG(3, ("%u entries returned in queue\n",
5417 if (cli && is_valid_policy_hnd(&handle)) {
5418 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
5423 END_PROFILE(SMBsplretq);
5427 /****************************************************************************
5428 Reply to a printwrite.
5429 ****************************************************************************/
5431 void reply_printwrite(struct smb_request *req)
5433 connection_struct *conn = req->conn;
5438 START_PROFILE(SMBsplwr);
5441 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5442 END_PROFILE(SMBsplwr);
5446 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5448 if (!check_fsp(conn, req, fsp)) {
5449 END_PROFILE(SMBsplwr);
5453 if (!fsp->print_file) {
5454 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5455 END_PROFILE(SMBsplwr);
5459 if (!CHECK_WRITE(fsp)) {
5460 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5461 END_PROFILE(SMBsplwr);
5465 numtowrite = SVAL(req->buf, 1);
5467 if (req->buflen < numtowrite + 3) {
5468 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5469 END_PROFILE(SMBsplwr);
5473 data = (const char *)req->buf + 3;
5475 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5476 reply_nterror(req, map_nt_error_from_unix(errno));
5477 END_PROFILE(SMBsplwr);
5481 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5483 END_PROFILE(SMBsplwr);
5487 /****************************************************************************
5489 ****************************************************************************/
5491 void reply_mkdir(struct smb_request *req)
5493 connection_struct *conn = req->conn;
5494 struct smb_filename *smb_dname = NULL;
5495 char *directory = NULL;
5497 TALLOC_CTX *ctx = talloc_tos();
5499 START_PROFILE(SMBmkdir);
5501 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5502 STR_TERMINATE, &status);
5503 if (!NT_STATUS_IS_OK(status)) {
5504 reply_nterror(req, status);
5508 status = filename_convert(ctx, conn,
5509 req->flags2 & FLAGS2_DFS_PATHNAMES,
5514 if (!NT_STATUS_IS_OK(status)) {
5515 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5516 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5517 ERRSRV, ERRbadpath);
5520 reply_nterror(req, status);
5524 status = create_directory(conn, req, smb_dname);
5526 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5528 if (!NT_STATUS_IS_OK(status)) {
5530 if (!use_nt_status()
5531 && NT_STATUS_EQUAL(status,
5532 NT_STATUS_OBJECT_NAME_COLLISION)) {
5534 * Yes, in the DOS error code case we get a
5535 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5536 * samba4 torture test.
5538 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5541 reply_nterror(req, status);
5545 reply_outbuf(req, 0, 0);
5547 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5549 TALLOC_FREE(smb_dname);
5550 END_PROFILE(SMBmkdir);
5554 /****************************************************************************
5556 ****************************************************************************/
5558 void reply_rmdir(struct smb_request *req)
5560 connection_struct *conn = req->conn;
5561 struct smb_filename *smb_dname = NULL;
5562 char *directory = NULL;
5564 TALLOC_CTX *ctx = talloc_tos();
5565 files_struct *fsp = NULL;
5567 struct smbd_server_connection *sconn = req->sconn;
5569 START_PROFILE(SMBrmdir);
5571 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5572 STR_TERMINATE, &status);
5573 if (!NT_STATUS_IS_OK(status)) {
5574 reply_nterror(req, status);
5578 status = filename_convert(ctx, conn,
5579 req->flags2 & FLAGS2_DFS_PATHNAMES,
5584 if (!NT_STATUS_IS_OK(status)) {
5585 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5586 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5587 ERRSRV, ERRbadpath);
5590 reply_nterror(req, status);
5594 if (is_ntfs_stream_smb_fname(smb_dname)) {
5595 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5599 status = SMB_VFS_CREATE_FILE(
5602 0, /* root_dir_fid */
5603 smb_dname, /* fname */
5604 DELETE_ACCESS, /* access_mask */
5605 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5607 FILE_OPEN, /* create_disposition*/
5608 FILE_DIRECTORY_FILE, /* create_options */
5609 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5610 0, /* oplock_request */
5611 0, /* allocation_size */
5612 0, /* private_flags */
5618 if (!NT_STATUS_IS_OK(status)) {
5619 if (open_was_deferred(req->mid)) {
5620 /* We have re-scheduled this call. */
5623 reply_nterror(req, status);
5627 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5628 if (!NT_STATUS_IS_OK(status)) {
5629 close_file(req, fsp, ERROR_CLOSE);
5630 reply_nterror(req, status);
5634 if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
5635 close_file(req, fsp, ERROR_CLOSE);
5636 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5640 status = close_file(req, fsp, NORMAL_CLOSE);
5641 if (!NT_STATUS_IS_OK(status)) {
5642 reply_nterror(req, status);
5644 reply_outbuf(req, 0, 0);
5647 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5649 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5651 TALLOC_FREE(smb_dname);
5652 END_PROFILE(SMBrmdir);
5656 /*******************************************************************
5657 Resolve wildcards in a filename rename.
5658 ********************************************************************/
5660 static bool resolve_wildcards(TALLOC_CTX *ctx,
5665 char *name2_copy = NULL;
5670 char *p,*p2, *pname1, *pname2;
5672 name2_copy = talloc_strdup(ctx, name2);
5677 pname1 = strrchr_m(name1,'/');
5678 pname2 = strrchr_m(name2_copy,'/');
5680 if (!pname1 || !pname2) {
5684 /* Truncate the copy of name2 at the last '/' */
5687 /* Now go past the '/' */
5691 root1 = talloc_strdup(ctx, pname1);
5692 root2 = talloc_strdup(ctx, pname2);
5694 if (!root1 || !root2) {
5698 p = strrchr_m(root1,'.');
5701 ext1 = talloc_strdup(ctx, p+1);
5703 ext1 = talloc_strdup(ctx, "");
5705 p = strrchr_m(root2,'.');
5708 ext2 = talloc_strdup(ctx, p+1);
5710 ext2 = talloc_strdup(ctx, "");
5713 if (!ext1 || !ext2) {
5721 /* Hmmm. Should this be mb-aware ? */
5724 } else if (*p2 == '*') {
5726 root2 = talloc_asprintf(ctx, "%s%s",
5745 /* Hmmm. Should this be mb-aware ? */
5748 } else if (*p2 == '*') {
5750 ext2 = talloc_asprintf(ctx, "%s%s",
5766 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5771 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5783 /****************************************************************************
5784 Ensure open files have their names updated. Updated to notify other smbd's
5786 ****************************************************************************/
5788 static void rename_open_files(connection_struct *conn,
5789 struct share_mode_lock *lck,
5790 const struct smb_filename *smb_fname_dst)
5793 bool did_rename = False;
5796 for(fsp = file_find_di_first(lck->id); fsp;
5797 fsp = file_find_di_next(fsp)) {
5798 /* fsp_name is a relative path under the fsp. To change this for other
5799 sharepaths we need to manipulate relative paths. */
5800 /* TODO - create the absolute path and manipulate the newname
5801 relative to the sharepath. */
5802 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5805 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5806 "(file_id %s) from %s -> %s\n", fsp->fnum,
5807 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5808 smb_fname_str_dbg(smb_fname_dst)));
5810 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5811 if (NT_STATUS_IS_OK(status)) {
5817 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5818 "for %s\n", file_id_string_tos(&lck->id),
5819 smb_fname_str_dbg(smb_fname_dst)));
5822 /* Send messages to all smbd's (not ourself) that the name has changed. */
5823 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5828 /****************************************************************************
5829 We need to check if the source path is a parent directory of the destination
5830 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5831 refuse the rename with a sharing violation. Under UNIX the above call can
5832 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5833 probably need to check that the client is a Windows one before disallowing
5834 this as a UNIX client (one with UNIX extensions) can know the source is a
5835 symlink and make this decision intelligently. Found by an excellent bug
5836 report from <AndyLiebman@aol.com>.
5837 ****************************************************************************/
5839 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5840 const struct smb_filename *smb_fname_dst)
5842 const char *psrc = smb_fname_src->base_name;
5843 const char *pdst = smb_fname_dst->base_name;
5846 if (psrc[0] == '.' && psrc[1] == '/') {
5849 if (pdst[0] == '.' && pdst[1] == '/') {
5852 if ((slen = strlen(psrc)) > strlen(pdst)) {
5855 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5859 * Do the notify calls from a rename
5862 static void notify_rename(connection_struct *conn, bool is_dir,
5863 const struct smb_filename *smb_fname_src,
5864 const struct smb_filename *smb_fname_dst)
5866 char *parent_dir_src = NULL;
5867 char *parent_dir_dst = NULL;
5870 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5871 : FILE_NOTIFY_CHANGE_FILE_NAME;
5873 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5874 &parent_dir_src, NULL) ||
5875 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5876 &parent_dir_dst, NULL)) {
5880 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5881 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5882 smb_fname_src->base_name);
5883 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5884 smb_fname_dst->base_name);
5887 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5888 smb_fname_src->base_name);
5889 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5890 smb_fname_dst->base_name);
5893 /* this is a strange one. w2k3 gives an additional event for
5894 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5895 files, but not directories */
5897 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5898 FILE_NOTIFY_CHANGE_ATTRIBUTES
5899 |FILE_NOTIFY_CHANGE_CREATION,
5900 smb_fname_dst->base_name);
5903 TALLOC_FREE(parent_dir_src);
5904 TALLOC_FREE(parent_dir_dst);
5907 /****************************************************************************
5908 Rename an open file - given an fsp.
5909 ****************************************************************************/
5911 NTSTATUS rename_internals_fsp(connection_struct *conn,
5913 const struct smb_filename *smb_fname_dst_in,
5915 bool replace_if_exists)
5917 TALLOC_CTX *ctx = talloc_tos();
5918 struct smb_filename *smb_fname_dst = NULL;
5919 NTSTATUS status = NT_STATUS_OK;
5920 struct share_mode_lock *lck = NULL;
5921 bool dst_exists, old_is_stream, new_is_stream;
5923 status = check_name(conn, smb_fname_dst_in->base_name);
5924 if (!NT_STATUS_IS_OK(status)) {
5928 /* Make a copy of the dst smb_fname structs */
5930 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5931 if (!NT_STATUS_IS_OK(status)) {
5935 /* Ensure the dst smb_fname contains a '/' */
5936 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5938 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5939 smb_fname_dst->base_name);
5941 status = NT_STATUS_NO_MEMORY;
5944 TALLOC_FREE(smb_fname_dst->base_name);
5945 smb_fname_dst->base_name = tmp;
5949 * Check for special case with case preserving and not
5950 * case sensitive. If the old last component differs from the original
5951 * last component only by case, then we should allow
5952 * the rename (user is trying to change the case of the
5955 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5956 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5957 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5959 char *fname_dst_lcomp_base_mod = NULL;
5960 struct smb_filename *smb_fname_orig_lcomp = NULL;
5963 * Get the last component of the destination name. Note that
5964 * we guarantee that destination name contains a '/' character
5967 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5968 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5969 if (!fname_dst_lcomp_base_mod) {
5970 status = NT_STATUS_NO_MEMORY;
5975 * Create an smb_filename struct using the original last
5976 * component of the destination.
5978 status = create_synthetic_smb_fname_split(ctx,
5979 smb_fname_dst->original_lcomp, NULL,
5980 &smb_fname_orig_lcomp);
5981 if (!NT_STATUS_IS_OK(status)) {
5982 TALLOC_FREE(fname_dst_lcomp_base_mod);
5986 /* If the base names only differ by case, use original. */
5987 if(!strcsequal(fname_dst_lcomp_base_mod,
5988 smb_fname_orig_lcomp->base_name)) {
5991 * Replace the modified last component with the
5994 *last_slash = '\0'; /* Truncate at the '/' */
5995 tmp = talloc_asprintf(smb_fname_dst,
5997 smb_fname_dst->base_name,
5998 smb_fname_orig_lcomp->base_name);
6000 status = NT_STATUS_NO_MEMORY;
6001 TALLOC_FREE(fname_dst_lcomp_base_mod);
6002 TALLOC_FREE(smb_fname_orig_lcomp);
6005 TALLOC_FREE(smb_fname_dst->base_name);
6006 smb_fname_dst->base_name = tmp;
6009 /* If the stream_names only differ by case, use original. */
6010 if(!strcsequal(smb_fname_dst->stream_name,
6011 smb_fname_orig_lcomp->stream_name)) {
6013 /* Use the original stream. */
6014 tmp = talloc_strdup(smb_fname_dst,
6015 smb_fname_orig_lcomp->stream_name);
6017 status = NT_STATUS_NO_MEMORY;
6018 TALLOC_FREE(fname_dst_lcomp_base_mod);
6019 TALLOC_FREE(smb_fname_orig_lcomp);
6022 TALLOC_FREE(smb_fname_dst->stream_name);
6023 smb_fname_dst->stream_name = tmp;
6025 TALLOC_FREE(fname_dst_lcomp_base_mod);
6026 TALLOC_FREE(smb_fname_orig_lcomp);
6030 * If the src and dest names are identical - including case,
6031 * don't do the rename, just return success.
6034 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6035 strcsequal(fsp->fsp_name->stream_name,
6036 smb_fname_dst->stream_name)) {
6037 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6038 "- returning success\n",
6039 smb_fname_str_dbg(smb_fname_dst)));
6040 status = NT_STATUS_OK;
6044 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6045 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6047 /* Return the correct error code if both names aren't streams. */
6048 if (!old_is_stream && new_is_stream) {
6049 status = NT_STATUS_OBJECT_NAME_INVALID;
6053 if (old_is_stream && !new_is_stream) {
6054 status = NT_STATUS_INVALID_PARAMETER;
6058 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6060 if(!replace_if_exists && dst_exists) {
6061 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6062 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6063 smb_fname_str_dbg(smb_fname_dst)));
6064 status = NT_STATUS_OBJECT_NAME_COLLISION;
6069 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6070 &smb_fname_dst->st);
6071 files_struct *dst_fsp = file_find_di_first(fileid);
6072 /* The file can be open when renaming a stream */
6073 if (dst_fsp && !new_is_stream) {
6074 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6075 status = NT_STATUS_ACCESS_DENIED;
6080 /* Ensure we have a valid stat struct for the source. */
6081 status = vfs_stat_fsp(fsp);
6082 if (!NT_STATUS_IS_OK(status)) {
6086 status = can_rename(conn, fsp, attrs);
6088 if (!NT_STATUS_IS_OK(status)) {
6089 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6090 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6091 smb_fname_str_dbg(smb_fname_dst)));
6092 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6093 status = NT_STATUS_ACCESS_DENIED;
6097 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6098 status = NT_STATUS_ACCESS_DENIED;
6101 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6105 * We have the file open ourselves, so not being able to get the
6106 * corresponding share mode lock is a fatal error.
6109 SMB_ASSERT(lck != NULL);
6111 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6112 uint32 create_options = fsp->fh->private_options;
6114 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6115 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6116 smb_fname_str_dbg(smb_fname_dst)));
6118 if (!lp_posix_pathnames() &&
6119 (lp_map_archive(SNUM(conn)) ||
6120 lp_store_dos_attributes(SNUM(conn)))) {
6121 /* We must set the archive bit on the newly
6123 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6124 uint32_t old_dosmode = dos_mode(conn,
6126 file_set_dosmode(conn,
6128 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6134 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6137 rename_open_files(conn, lck, smb_fname_dst);
6140 * A rename acts as a new file create w.r.t. allowing an initial delete
6141 * on close, probably because in Windows there is a new handle to the
6142 * new file. If initial delete on close was requested but not
6143 * originally set, we need to set it here. This is probably not 100% correct,
6144 * but will work for the CIFSFS client which in non-posix mode
6145 * depends on these semantics. JRA.
6148 if (create_options & FILE_DELETE_ON_CLOSE) {
6149 status = can_set_delete_on_close(fsp, 0);
6151 if (NT_STATUS_IS_OK(status)) {
6152 /* Note that here we set the *inital* delete on close flag,
6153 * not the regular one. The magic gets handled in close. */
6154 fsp->initial_delete_on_close = True;
6158 status = NT_STATUS_OK;
6164 if (errno == ENOTDIR || errno == EISDIR) {
6165 status = NT_STATUS_OBJECT_NAME_COLLISION;
6167 status = map_nt_error_from_unix(errno);
6170 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6171 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6172 smb_fname_str_dbg(smb_fname_dst)));
6175 TALLOC_FREE(smb_fname_dst);
6180 /****************************************************************************
6181 The guts of the rename command, split out so it may be called by the NT SMB
6183 ****************************************************************************/
6185 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6186 connection_struct *conn,
6187 struct smb_request *req,
6188 struct smb_filename *smb_fname_src,
6189 struct smb_filename *smb_fname_dst,
6191 bool replace_if_exists,
6194 uint32_t access_mask)
6196 char *fname_src_dir = NULL;
6197 char *fname_src_mask = NULL;
6199 NTSTATUS status = NT_STATUS_OK;
6200 struct smb_Dir *dir_hnd = NULL;
6201 const char *dname = NULL;
6202 char *talloced = NULL;
6204 int create_options = 0;
6205 bool posix_pathnames = lp_posix_pathnames();
6208 * Split the old name into directory and last component
6209 * strings. Note that unix_convert may have stripped off a
6210 * leading ./ from both name and newname if the rename is
6211 * at the root of the share. We need to make sure either both
6212 * name and newname contain a / character or neither of them do
6213 * as this is checked in resolve_wildcards().
6216 /* Split up the directory from the filename/mask. */
6217 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6218 &fname_src_dir, &fname_src_mask);
6219 if (!NT_STATUS_IS_OK(status)) {
6220 status = NT_STATUS_NO_MEMORY;
6225 * We should only check the mangled cache
6226 * here if unix_convert failed. This means
6227 * that the path in 'mask' doesn't exist
6228 * on the file system and so we need to look
6229 * for a possible mangle. This patch from
6230 * Tine Smukavec <valentin.smukavec@hermes.si>.
6233 if (!VALID_STAT(smb_fname_src->st) &&
6234 mangle_is_mangled(fname_src_mask, conn->params)) {
6235 char *new_mask = NULL;
6236 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6239 TALLOC_FREE(fname_src_mask);
6240 fname_src_mask = new_mask;
6244 if (!src_has_wild) {
6248 * Only one file needs to be renamed. Append the mask back
6249 * onto the directory.
6251 TALLOC_FREE(smb_fname_src->base_name);
6252 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6256 if (!smb_fname_src->base_name) {
6257 status = NT_STATUS_NO_MEMORY;
6261 /* Ensure dst fname contains a '/' also */
6262 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6264 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6265 smb_fname_dst->base_name);
6267 status = NT_STATUS_NO_MEMORY;
6270 TALLOC_FREE(smb_fname_dst->base_name);
6271 smb_fname_dst->base_name = tmp;
6274 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6275 "case_preserve = %d, short case preserve = %d, "
6276 "directory = %s, newname = %s, "
6277 "last_component_dest = %s\n",
6278 conn->case_sensitive, conn->case_preserve,
6279 conn->short_case_preserve,
6280 smb_fname_str_dbg(smb_fname_src),
6281 smb_fname_str_dbg(smb_fname_dst),
6282 smb_fname_dst->original_lcomp));
6284 /* The dest name still may have wildcards. */
6285 if (dest_has_wild) {
6286 char *fname_dst_mod = NULL;
6287 if (!resolve_wildcards(smb_fname_dst,
6288 smb_fname_src->base_name,
6289 smb_fname_dst->base_name,
6291 DEBUG(6, ("rename_internals: resolve_wildcards "
6293 smb_fname_src->base_name,
6294 smb_fname_dst->base_name));
6295 status = NT_STATUS_NO_MEMORY;
6298 TALLOC_FREE(smb_fname_dst->base_name);
6299 smb_fname_dst->base_name = fname_dst_mod;
6302 ZERO_STRUCT(smb_fname_src->st);
6303 if (posix_pathnames) {
6304 SMB_VFS_LSTAT(conn, smb_fname_src);
6306 SMB_VFS_STAT(conn, smb_fname_src);
6309 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6310 create_options |= FILE_DIRECTORY_FILE;
6313 status = SMB_VFS_CREATE_FILE(
6316 0, /* root_dir_fid */
6317 smb_fname_src, /* fname */
6318 access_mask, /* access_mask */
6319 (FILE_SHARE_READ | /* share_access */
6321 FILE_OPEN, /* create_disposition*/
6322 create_options, /* create_options */
6323 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6324 0, /* oplock_request */
6325 0, /* allocation_size */
6326 0, /* private_flags */
6332 if (!NT_STATUS_IS_OK(status)) {
6333 DEBUG(3, ("Could not open rename source %s: %s\n",
6334 smb_fname_str_dbg(smb_fname_src),
6335 nt_errstr(status)));
6339 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6340 attrs, replace_if_exists);
6342 close_file(req, fsp, NORMAL_CLOSE);
6344 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6345 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6346 smb_fname_str_dbg(smb_fname_dst)));
6352 * Wildcards - process each file that matches.
6354 if (strequal(fname_src_mask, "????????.???")) {
6355 TALLOC_FREE(fname_src_mask);
6356 fname_src_mask = talloc_strdup(ctx, "*");
6357 if (!fname_src_mask) {
6358 status = NT_STATUS_NO_MEMORY;
6363 status = check_name(conn, fname_src_dir);
6364 if (!NT_STATUS_IS_OK(status)) {
6368 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6370 if (dir_hnd == NULL) {
6371 status = map_nt_error_from_unix(errno);
6375 status = NT_STATUS_NO_SUCH_FILE;
6377 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6378 * - gentest fix. JRA
6381 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6383 files_struct *fsp = NULL;
6384 char *destname = NULL;
6385 bool sysdir_entry = False;
6387 /* Quick check for "." and ".." */
6388 if (ISDOT(dname) || ISDOTDOT(dname)) {
6390 sysdir_entry = True;
6392 TALLOC_FREE(talloced);
6397 if (!is_visible_file(conn, fname_src_dir, dname,
6398 &smb_fname_src->st, false)) {
6399 TALLOC_FREE(talloced);
6403 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6404 TALLOC_FREE(talloced);
6409 status = NT_STATUS_OBJECT_NAME_INVALID;
6413 TALLOC_FREE(smb_fname_src->base_name);
6414 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6418 if (!smb_fname_src->base_name) {
6419 status = NT_STATUS_NO_MEMORY;
6423 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6424 smb_fname_dst->base_name,
6426 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6427 smb_fname_src->base_name, destname));
6428 TALLOC_FREE(talloced);
6432 status = NT_STATUS_NO_MEMORY;
6436 TALLOC_FREE(smb_fname_dst->base_name);
6437 smb_fname_dst->base_name = destname;
6439 ZERO_STRUCT(smb_fname_src->st);
6440 if (posix_pathnames) {
6441 SMB_VFS_LSTAT(conn, smb_fname_src);
6443 SMB_VFS_STAT(conn, smb_fname_src);
6448 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6449 create_options |= FILE_DIRECTORY_FILE;
6452 status = SMB_VFS_CREATE_FILE(
6455 0, /* root_dir_fid */
6456 smb_fname_src, /* fname */
6457 access_mask, /* access_mask */
6458 (FILE_SHARE_READ | /* share_access */
6460 FILE_OPEN, /* create_disposition*/
6461 create_options, /* create_options */
6462 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6463 0, /* oplock_request */
6464 0, /* allocation_size */
6465 0, /* private_flags */
6471 if (!NT_STATUS_IS_OK(status)) {
6472 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6473 "returned %s rename %s -> %s\n",
6475 smb_fname_str_dbg(smb_fname_src),
6476 smb_fname_str_dbg(smb_fname_dst)));
6480 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6482 if (!smb_fname_dst->original_lcomp) {
6483 status = NT_STATUS_NO_MEMORY;
6487 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6488 attrs, replace_if_exists);
6490 close_file(req, fsp, NORMAL_CLOSE);
6492 if (!NT_STATUS_IS_OK(status)) {
6493 DEBUG(3, ("rename_internals_fsp returned %s for "
6494 "rename %s -> %s\n", nt_errstr(status),
6495 smb_fname_str_dbg(smb_fname_src),
6496 smb_fname_str_dbg(smb_fname_dst)));
6502 DEBUG(3,("rename_internals: doing rename on %s -> "
6503 "%s\n", smb_fname_str_dbg(smb_fname_src),
6504 smb_fname_str_dbg(smb_fname_src)));
6505 TALLOC_FREE(talloced);
6507 TALLOC_FREE(dir_hnd);
6509 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6510 status = map_nt_error_from_unix(errno);
6514 TALLOC_FREE(talloced);
6515 TALLOC_FREE(fname_src_dir);
6516 TALLOC_FREE(fname_src_mask);
6520 /****************************************************************************
6522 ****************************************************************************/
6524 void reply_mv(struct smb_request *req)
6526 connection_struct *conn = req->conn;
6528 char *newname = NULL;
6532 bool src_has_wcard = False;
6533 bool dest_has_wcard = False;
6534 TALLOC_CTX *ctx = talloc_tos();
6535 struct smb_filename *smb_fname_src = NULL;
6536 struct smb_filename *smb_fname_dst = NULL;
6538 START_PROFILE(SMBmv);
6541 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6545 attrs = SVAL(req->vwv+0, 0);
6547 p = (const char *)req->buf + 1;
6548 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6549 &status, &src_has_wcard);
6550 if (!NT_STATUS_IS_OK(status)) {
6551 reply_nterror(req, status);
6555 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6556 &status, &dest_has_wcard);
6557 if (!NT_STATUS_IS_OK(status)) {
6558 reply_nterror(req, status);
6562 status = filename_convert(ctx,
6564 req->flags2 & FLAGS2_DFS_PATHNAMES,
6566 UCF_COND_ALLOW_WCARD_LCOMP,
6570 if (!NT_STATUS_IS_OK(status)) {
6571 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6572 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6573 ERRSRV, ERRbadpath);
6576 reply_nterror(req, status);
6580 status = filename_convert(ctx,
6582 req->flags2 & FLAGS2_DFS_PATHNAMES,
6584 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6588 if (!NT_STATUS_IS_OK(status)) {
6589 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6590 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6591 ERRSRV, ERRbadpath);
6594 reply_nterror(req, status);
6598 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6599 smb_fname_str_dbg(smb_fname_dst)));
6601 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6602 attrs, False, src_has_wcard, dest_has_wcard,
6604 if (!NT_STATUS_IS_OK(status)) {
6605 if (open_was_deferred(req->mid)) {
6606 /* We have re-scheduled this call. */
6609 reply_nterror(req, status);
6613 reply_outbuf(req, 0, 0);
6615 TALLOC_FREE(smb_fname_src);
6616 TALLOC_FREE(smb_fname_dst);
6621 /*******************************************************************
6622 Copy a file as part of a reply_copy.
6623 ******************************************************************/
6626 * TODO: check error codes on all callers
6629 NTSTATUS copy_file(TALLOC_CTX *ctx,
6630 connection_struct *conn,
6631 struct smb_filename *smb_fname_src,
6632 struct smb_filename *smb_fname_dst,
6635 bool target_is_directory)
6637 struct smb_filename *smb_fname_dst_tmp = NULL;
6639 files_struct *fsp1,*fsp2;
6641 uint32 new_create_disposition;
6645 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6646 if (!NT_STATUS_IS_OK(status)) {
6651 * If the target is a directory, extract the last component from the
6652 * src filename and append it to the dst filename
6654 if (target_is_directory) {
6657 /* dest/target can't be a stream if it's a directory. */
6658 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6660 p = strrchr_m(smb_fname_src->base_name,'/');
6664 p = smb_fname_src->base_name;
6666 smb_fname_dst_tmp->base_name =
6667 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6669 if (!smb_fname_dst_tmp->base_name) {
6670 status = NT_STATUS_NO_MEMORY;
6675 status = vfs_file_exist(conn, smb_fname_src);
6676 if (!NT_STATUS_IS_OK(status)) {
6680 if (!target_is_directory && count) {
6681 new_create_disposition = FILE_OPEN;
6683 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6685 &new_create_disposition,
6688 status = NT_STATUS_INVALID_PARAMETER;
6693 /* Open the src file for reading. */
6694 status = SMB_VFS_CREATE_FILE(
6697 0, /* root_dir_fid */
6698 smb_fname_src, /* fname */
6699 FILE_GENERIC_READ, /* access_mask */
6700 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6701 FILE_OPEN, /* create_disposition*/
6702 0, /* create_options */
6703 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6704 INTERNAL_OPEN_ONLY, /* oplock_request */
6705 0, /* allocation_size */
6706 0, /* private_flags */
6712 if (!NT_STATUS_IS_OK(status)) {
6716 dosattrs = dos_mode(conn, smb_fname_src);
6718 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6719 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6722 /* Open the dst file for writing. */
6723 status = SMB_VFS_CREATE_FILE(
6726 0, /* root_dir_fid */
6727 smb_fname_dst, /* fname */
6728 FILE_GENERIC_WRITE, /* access_mask */
6729 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6730 new_create_disposition, /* create_disposition*/
6731 0, /* create_options */
6732 dosattrs, /* file_attributes */
6733 INTERNAL_OPEN_ONLY, /* oplock_request */
6734 0, /* allocation_size */
6735 0, /* private_flags */
6741 if (!NT_STATUS_IS_OK(status)) {
6742 close_file(NULL, fsp1, ERROR_CLOSE);
6746 if ((ofun&3) == 1) {
6747 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6748 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6750 * Stop the copy from occurring.
6753 smb_fname_src->st.st_ex_size = 0;
6757 /* Do the actual copy. */
6758 if (smb_fname_src->st.st_ex_size) {
6759 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6762 close_file(NULL, fsp1, NORMAL_CLOSE);
6764 /* Ensure the modtime is set correctly on the destination file. */
6765 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6768 * As we are opening fsp1 read-only we only expect
6769 * an error on close on fsp2 if we are out of space.
6770 * Thus we don't look at the error return from the
6773 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6775 if (!NT_STATUS_IS_OK(status)) {
6779 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6780 status = NT_STATUS_DISK_FULL;
6784 status = NT_STATUS_OK;
6787 TALLOC_FREE(smb_fname_dst_tmp);
6791 /****************************************************************************
6792 Reply to a file copy.
6793 ****************************************************************************/
6795 void reply_copy(struct smb_request *req)
6797 connection_struct *conn = req->conn;
6798 struct smb_filename *smb_fname_src = NULL;
6799 struct smb_filename *smb_fname_dst = NULL;
6800 char *fname_src = NULL;
6801 char *fname_dst = NULL;
6802 char *fname_src_mask = NULL;
6803 char *fname_src_dir = NULL;
6806 int error = ERRnoaccess;
6810 bool target_is_directory=False;
6811 bool source_has_wild = False;
6812 bool dest_has_wild = False;
6814 TALLOC_CTX *ctx = talloc_tos();
6816 START_PROFILE(SMBcopy);
6819 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6823 tid2 = SVAL(req->vwv+0, 0);
6824 ofun = SVAL(req->vwv+1, 0);
6825 flags = SVAL(req->vwv+2, 0);
6827 p = (const char *)req->buf;
6828 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6829 &status, &source_has_wild);
6830 if (!NT_STATUS_IS_OK(status)) {
6831 reply_nterror(req, status);
6834 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6835 &status, &dest_has_wild);
6836 if (!NT_STATUS_IS_OK(status)) {
6837 reply_nterror(req, status);
6841 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6843 if (tid2 != conn->cnum) {
6844 /* can't currently handle inter share copies XXXX */
6845 DEBUG(3,("Rejecting inter-share copy\n"));
6846 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6850 status = filename_convert(ctx, conn,
6851 req->flags2 & FLAGS2_DFS_PATHNAMES,
6853 UCF_COND_ALLOW_WCARD_LCOMP,
6856 if (!NT_STATUS_IS_OK(status)) {
6857 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6858 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6859 ERRSRV, ERRbadpath);
6862 reply_nterror(req, status);
6866 status = filename_convert(ctx, conn,
6867 req->flags2 & FLAGS2_DFS_PATHNAMES,
6869 UCF_COND_ALLOW_WCARD_LCOMP,
6872 if (!NT_STATUS_IS_OK(status)) {
6873 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6874 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6875 ERRSRV, ERRbadpath);
6878 reply_nterror(req, status);
6882 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6884 if ((flags&1) && target_is_directory) {
6885 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6889 if ((flags&2) && !target_is_directory) {
6890 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6894 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6895 /* wants a tree copy! XXXX */
6896 DEBUG(3,("Rejecting tree copy\n"));
6897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6901 /* Split up the directory from the filename/mask. */
6902 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6903 &fname_src_dir, &fname_src_mask);
6904 if (!NT_STATUS_IS_OK(status)) {
6905 reply_nterror(req, NT_STATUS_NO_MEMORY);
6910 * We should only check the mangled cache
6911 * here if unix_convert failed. This means
6912 * that the path in 'mask' doesn't exist
6913 * on the file system and so we need to look
6914 * for a possible mangle. This patch from
6915 * Tine Smukavec <valentin.smukavec@hermes.si>.
6917 if (!VALID_STAT(smb_fname_src->st) &&
6918 mangle_is_mangled(fname_src_mask, conn->params)) {
6919 char *new_mask = NULL;
6920 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6921 &new_mask, conn->params);
6923 /* Use demangled name if one was successfully found. */
6925 TALLOC_FREE(fname_src_mask);
6926 fname_src_mask = new_mask;
6930 if (!source_has_wild) {
6933 * Only one file needs to be copied. Append the mask back onto
6936 TALLOC_FREE(smb_fname_src->base_name);
6937 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6941 if (!smb_fname_src->base_name) {
6942 reply_nterror(req, NT_STATUS_NO_MEMORY);
6946 if (dest_has_wild) {
6947 char *fname_dst_mod = NULL;
6948 if (!resolve_wildcards(smb_fname_dst,
6949 smb_fname_src->base_name,
6950 smb_fname_dst->base_name,
6952 reply_nterror(req, NT_STATUS_NO_MEMORY);
6955 TALLOC_FREE(smb_fname_dst->base_name);
6956 smb_fname_dst->base_name = fname_dst_mod;
6959 status = check_name(conn, smb_fname_src->base_name);
6960 if (!NT_STATUS_IS_OK(status)) {
6961 reply_nterror(req, status);
6965 status = check_name(conn, smb_fname_dst->base_name);
6966 if (!NT_STATUS_IS_OK(status)) {
6967 reply_nterror(req, status);
6971 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6972 ofun, count, target_is_directory);
6974 if(!NT_STATUS_IS_OK(status)) {
6975 reply_nterror(req, status);
6981 struct smb_Dir *dir_hnd = NULL;
6982 const char *dname = NULL;
6983 char *talloced = NULL;
6987 * There is a wildcard that requires us to actually read the
6988 * src dir and copy each file matching the mask to the dst.
6989 * Right now streams won't be copied, but this could
6990 * presumably be added with a nested loop for reach dir entry.
6992 SMB_ASSERT(!smb_fname_src->stream_name);
6993 SMB_ASSERT(!smb_fname_dst->stream_name);
6995 smb_fname_src->stream_name = NULL;
6996 smb_fname_dst->stream_name = NULL;
6998 if (strequal(fname_src_mask,"????????.???")) {
6999 TALLOC_FREE(fname_src_mask);
7000 fname_src_mask = talloc_strdup(ctx, "*");
7001 if (!fname_src_mask) {
7002 reply_nterror(req, NT_STATUS_NO_MEMORY);
7007 status = check_name(conn, fname_src_dir);
7008 if (!NT_STATUS_IS_OK(status)) {
7009 reply_nterror(req, status);
7013 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7014 if (dir_hnd == NULL) {
7015 status = map_nt_error_from_unix(errno);
7016 reply_nterror(req, status);
7022 /* Iterate over the src dir copying each entry to the dst. */
7023 while ((dname = ReadDirName(dir_hnd, &offset,
7024 &smb_fname_src->st, &talloced))) {
7025 char *destname = NULL;
7027 if (ISDOT(dname) || ISDOTDOT(dname)) {
7028 TALLOC_FREE(talloced);
7032 if (!is_visible_file(conn, fname_src_dir, dname,
7033 &smb_fname_src->st, false)) {
7034 TALLOC_FREE(talloced);
7038 if(!mask_match(dname, fname_src_mask,
7039 conn->case_sensitive)) {
7040 TALLOC_FREE(talloced);
7044 error = ERRnoaccess;
7046 /* Get the src smb_fname struct setup. */
7047 TALLOC_FREE(smb_fname_src->base_name);
7048 smb_fname_src->base_name =
7049 talloc_asprintf(smb_fname_src, "%s/%s",
7050 fname_src_dir, dname);
7052 if (!smb_fname_src->base_name) {
7053 TALLOC_FREE(dir_hnd);
7054 TALLOC_FREE(talloced);
7055 reply_nterror(req, NT_STATUS_NO_MEMORY);
7059 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7060 smb_fname_dst->base_name,
7062 TALLOC_FREE(talloced);
7066 TALLOC_FREE(dir_hnd);
7067 TALLOC_FREE(talloced);
7068 reply_nterror(req, NT_STATUS_NO_MEMORY);
7072 TALLOC_FREE(smb_fname_dst->base_name);
7073 smb_fname_dst->base_name = destname;
7075 status = check_name(conn, smb_fname_src->base_name);
7076 if (!NT_STATUS_IS_OK(status)) {
7077 TALLOC_FREE(dir_hnd);
7078 TALLOC_FREE(talloced);
7079 reply_nterror(req, status);
7083 status = check_name(conn, smb_fname_dst->base_name);
7084 if (!NT_STATUS_IS_OK(status)) {
7085 TALLOC_FREE(dir_hnd);
7086 TALLOC_FREE(talloced);
7087 reply_nterror(req, status);
7091 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7092 smb_fname_src->base_name,
7093 smb_fname_dst->base_name));
7095 status = copy_file(ctx, conn, smb_fname_src,
7096 smb_fname_dst, ofun, count,
7097 target_is_directory);
7098 if (NT_STATUS_IS_OK(status)) {
7102 TALLOC_FREE(talloced);
7104 TALLOC_FREE(dir_hnd);
7108 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7112 reply_outbuf(req, 1, 0);
7113 SSVAL(req->outbuf,smb_vwv0,count);
7115 TALLOC_FREE(smb_fname_src);
7116 TALLOC_FREE(smb_fname_dst);
7117 TALLOC_FREE(fname_src);
7118 TALLOC_FREE(fname_dst);
7119 TALLOC_FREE(fname_src_mask);
7120 TALLOC_FREE(fname_src_dir);
7122 END_PROFILE(SMBcopy);
7127 #define DBGC_CLASS DBGC_LOCKING
7129 /****************************************************************************
7130 Get a lock pid, dealing with large count requests.
7131 ****************************************************************************/
7133 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7134 bool large_file_format)
7136 if(!large_file_format)
7137 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7139 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7142 /****************************************************************************
7143 Get a lock count, dealing with large count requests.
7144 ****************************************************************************/
7146 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7147 bool large_file_format)
7151 if(!large_file_format) {
7152 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7155 #if defined(HAVE_LONGLONG)
7156 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7157 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7158 #else /* HAVE_LONGLONG */
7161 * NT4.x seems to be broken in that it sends large file (64 bit)
7162 * lockingX calls even if the CAP_LARGE_FILES was *not*
7163 * negotiated. For boxes without large unsigned ints truncate the
7164 * lock count by dropping the top 32 bits.
7167 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7168 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7169 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7170 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7171 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7174 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7175 #endif /* HAVE_LONGLONG */
7181 #if !defined(HAVE_LONGLONG)
7182 /****************************************************************************
7183 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7184 ****************************************************************************/
7186 static uint32 map_lock_offset(uint32 high, uint32 low)
7190 uint32 highcopy = high;
7193 * Try and find out how many significant bits there are in high.
7196 for(i = 0; highcopy; i++)
7200 * We use 31 bits not 32 here as POSIX
7201 * lock offsets may not be negative.
7204 mask = (~0) << (31 - i);
7207 return 0; /* Fail. */
7213 #endif /* !defined(HAVE_LONGLONG) */
7215 /****************************************************************************
7216 Get a lock offset, dealing with large offset requests.
7217 ****************************************************************************/
7219 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7220 bool large_file_format, bool *err)
7222 uint64_t offset = 0;
7226 if(!large_file_format) {
7227 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7230 #if defined(HAVE_LONGLONG)
7231 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7232 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7233 #else /* HAVE_LONGLONG */
7236 * NT4.x seems to be broken in that it sends large file (64 bit)
7237 * lockingX calls even if the CAP_LARGE_FILES was *not*
7238 * negotiated. For boxes without large unsigned ints mangle the
7239 * lock offset by mapping the top 32 bits onto the lower 32.
7242 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7243 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7244 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7247 if((new_low = map_lock_offset(high, low)) == 0) {
7249 return (uint64_t)-1;
7252 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7253 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7254 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7255 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7258 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7259 #endif /* HAVE_LONGLONG */
7265 NTSTATUS smbd_do_locking(struct smb_request *req,
7269 uint16_t num_ulocks,
7270 struct smbd_lock_element *ulocks,
7272 struct smbd_lock_element *locks,
7275 connection_struct *conn = req->conn;
7277 NTSTATUS status = NT_STATUS_OK;
7281 /* Data now points at the beginning of the list
7282 of smb_unlkrng structs */
7283 for(i = 0; i < (int)num_ulocks; i++) {
7284 struct smbd_lock_element *e = &ulocks[i];
7286 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7287 "pid %u, file %s\n",
7290 (unsigned int)e->smblctx,
7293 if (e->brltype != UNLOCK_LOCK) {
7294 /* this can only happen with SMB2 */
7295 return NT_STATUS_INVALID_PARAMETER;
7298 status = do_unlock(req->sconn->msg_ctx,
7305 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7306 nt_errstr(status)));
7308 if (!NT_STATUS_IS_OK(status)) {
7313 /* Setup the timeout in seconds. */
7315 if (!lp_blocking_locks(SNUM(conn))) {
7319 /* Data now points at the beginning of the list
7320 of smb_lkrng structs */
7322 for(i = 0; i < (int)num_locks; i++) {
7323 struct smbd_lock_element *e = &locks[i];
7325 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7326 "%llu, file %s timeout = %d\n",
7329 (unsigned long long)e->smblctx,
7333 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7334 struct blocking_lock_record *blr = NULL;
7336 if (num_locks > 1) {
7338 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7339 * if the lock vector contains one entry. When given mutliple cancel
7340 * requests in a single PDU we expect the server to return an
7341 * error. Windows servers seem to accept the request but only
7342 * cancel the first lock.
7343 * JRA - Do what Windows does (tm) :-).
7347 /* MS-CIFS (2.2.4.32.1) behavior. */
7348 return NT_STATUS_DOS(ERRDOS,
7349 ERRcancelviolation);
7351 /* Windows behavior. */
7353 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7354 "cancel request\n"));
7360 if (lp_blocking_locks(SNUM(conn))) {
7362 /* Schedule a message to ourselves to
7363 remove the blocking lock record and
7364 return the right error. */
7366 blr = blocking_lock_cancel_smb1(fsp,
7372 NT_STATUS_FILE_LOCK_CONFLICT);
7374 return NT_STATUS_DOS(
7376 ERRcancelviolation);
7379 /* Remove a matching pending lock. */
7380 status = do_lock_cancel(fsp,
7387 bool blocking_lock = timeout ? true : false;
7388 bool defer_lock = false;
7389 struct byte_range_lock *br_lck;
7390 uint64_t block_smblctx;
7392 br_lck = do_lock(req->sconn->msg_ctx,
7404 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7405 /* Windows internal resolution for blocking locks seems
7406 to be about 200ms... Don't wait for less than that. JRA. */
7407 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7408 timeout = lp_lock_spin_time();
7413 /* If a lock sent with timeout of zero would fail, and
7414 * this lock has been requested multiple times,
7415 * according to brl_lock_failed() we convert this
7416 * request to a blocking lock with a timeout of between
7417 * 150 - 300 milliseconds.
7419 * If lp_lock_spin_time() has been set to 0, we skip
7420 * this blocking retry and fail immediately.
7422 * Replacement for do_lock_spin(). JRA. */
7424 if (!req->sconn->using_smb2 &&
7425 br_lck && lp_blocking_locks(SNUM(conn)) &&
7426 lp_lock_spin_time() && !blocking_lock &&
7427 NT_STATUS_EQUAL((status),
7428 NT_STATUS_FILE_LOCK_CONFLICT))
7431 timeout = lp_lock_spin_time();
7434 if (br_lck && defer_lock) {
7436 * A blocking lock was requested. Package up
7437 * this smb into a queued request and push it
7438 * onto the blocking lock queue.
7440 if(push_blocking_lock_request(br_lck,
7451 TALLOC_FREE(br_lck);
7453 return NT_STATUS_OK;
7457 TALLOC_FREE(br_lck);
7460 if (!NT_STATUS_IS_OK(status)) {
7465 /* If any of the above locks failed, then we must unlock
7466 all of the previous locks (X/Open spec). */
7468 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7470 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7471 i = -1; /* we want to skip the for loop */
7475 * Ensure we don't do a remove on the lock that just failed,
7476 * as under POSIX rules, if we have a lock already there, we
7477 * will delete it (and we shouldn't) .....
7479 for(i--; i >= 0; i--) {
7480 struct smbd_lock_element *e = &locks[i];
7482 do_unlock(req->sconn->msg_ctx,
7492 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7493 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7495 return NT_STATUS_OK;
7498 /****************************************************************************
7499 Reply to a lockingX request.
7500 ****************************************************************************/
7502 void reply_lockingX(struct smb_request *req)
7504 connection_struct *conn = req->conn;
7506 unsigned char locktype;
7507 unsigned char oplocklevel;
7512 const uint8_t *data;
7513 bool large_file_format;
7515 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7516 struct smbd_lock_element *ulocks;
7517 struct smbd_lock_element *locks;
7520 START_PROFILE(SMBlockingX);
7523 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7524 END_PROFILE(SMBlockingX);
7528 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7529 locktype = CVAL(req->vwv+3, 0);
7530 oplocklevel = CVAL(req->vwv+3, 1);
7531 num_ulocks = SVAL(req->vwv+6, 0);
7532 num_locks = SVAL(req->vwv+7, 0);
7533 lock_timeout = IVAL(req->vwv+4, 0);
7534 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7536 if (!check_fsp(conn, req, fsp)) {
7537 END_PROFILE(SMBlockingX);
7543 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7544 /* we don't support these - and CANCEL_LOCK makes w2k
7545 and XP reboot so I don't really want to be
7546 compatible! (tridge) */
7547 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7548 END_PROFILE(SMBlockingX);
7552 /* Check if this is an oplock break on a file
7553 we have granted an oplock on.
7555 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7556 /* Client can insist on breaking to none. */
7557 bool break_to_none = (oplocklevel == 0);
7560 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7561 "for fnum = %d\n", (unsigned int)oplocklevel,
7565 * Make sure we have granted an exclusive or batch oplock on
7569 if (fsp->oplock_type == 0) {
7571 /* The Samba4 nbench simulator doesn't understand
7572 the difference between break to level2 and break
7573 to none from level2 - it sends oplock break
7574 replies in both cases. Don't keep logging an error
7575 message here - just ignore it. JRA. */
7577 DEBUG(5,("reply_lockingX: Error : oplock break from "
7578 "client for fnum = %d (oplock=%d) and no "
7579 "oplock granted on this file (%s).\n",
7580 fsp->fnum, fsp->oplock_type,
7583 /* if this is a pure oplock break request then don't
7585 if (num_locks == 0 && num_ulocks == 0) {
7586 END_PROFILE(SMBlockingX);
7589 END_PROFILE(SMBlockingX);
7590 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7595 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7597 result = remove_oplock(fsp);
7599 result = downgrade_oplock(fsp);
7603 DEBUG(0, ("reply_lockingX: error in removing "
7604 "oplock on file %s\n", fsp_str_dbg(fsp)));
7605 /* Hmmm. Is this panic justified? */
7606 smb_panic("internal tdb error");
7609 reply_to_oplock_break_requests(fsp);
7611 /* if this is a pure oplock break request then don't send a
7613 if (num_locks == 0 && num_ulocks == 0) {
7614 /* Sanity check - ensure a pure oplock break is not a
7616 if(CVAL(req->vwv+0, 0) != 0xff)
7617 DEBUG(0,("reply_lockingX: Error : pure oplock "
7618 "break is a chained %d request !\n",
7619 (unsigned int)CVAL(req->vwv+0, 0)));
7620 END_PROFILE(SMBlockingX);
7626 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7627 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7628 END_PROFILE(SMBlockingX);
7632 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7633 if (ulocks == NULL) {
7634 reply_nterror(req, NT_STATUS_NO_MEMORY);
7635 END_PROFILE(SMBlockingX);
7639 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7640 if (locks == NULL) {
7641 reply_nterror(req, NT_STATUS_NO_MEMORY);
7642 END_PROFILE(SMBlockingX);
7646 /* Data now points at the beginning of the list
7647 of smb_unlkrng structs */
7648 for(i = 0; i < (int)num_ulocks; i++) {
7649 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7650 ulocks[i].count = get_lock_count(data, i, large_file_format);
7651 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7652 ulocks[i].brltype = UNLOCK_LOCK;
7655 * There is no error code marked "stupid client bug".... :-).
7658 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7659 END_PROFILE(SMBlockingX);
7664 /* Now do any requested locks */
7665 data += ((large_file_format ? 20 : 10)*num_ulocks);
7667 /* Data now points at the beginning of the list
7668 of smb_lkrng structs */
7670 for(i = 0; i < (int)num_locks; i++) {
7671 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7672 locks[i].count = get_lock_count(data, i, large_file_format);
7673 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7675 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7676 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7677 locks[i].brltype = PENDING_READ_LOCK;
7679 locks[i].brltype = READ_LOCK;
7682 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7683 locks[i].brltype = PENDING_WRITE_LOCK;
7685 locks[i].brltype = WRITE_LOCK;
7690 * There is no error code marked "stupid client bug".... :-).
7693 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7694 END_PROFILE(SMBlockingX);
7699 status = smbd_do_locking(req, fsp,
7700 locktype, lock_timeout,
7704 if (!NT_STATUS_IS_OK(status)) {
7705 END_PROFILE(SMBlockingX);
7706 reply_nterror(req, status);
7710 END_PROFILE(SMBlockingX);
7714 reply_outbuf(req, 2, 0);
7716 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7717 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7719 END_PROFILE(SMBlockingX);
7724 #define DBGC_CLASS DBGC_ALL
7726 /****************************************************************************
7727 Reply to a SMBreadbmpx (read block multiplex) request.
7728 Always reply with an error, if someone has a platform really needs this,
7729 please contact vl@samba.org
7730 ****************************************************************************/
7732 void reply_readbmpx(struct smb_request *req)
7734 START_PROFILE(SMBreadBmpx);
7735 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7736 END_PROFILE(SMBreadBmpx);
7740 /****************************************************************************
7741 Reply to a SMBreadbs (read block multiplex secondary) request.
7742 Always reply with an error, if someone has a platform really needs this,
7743 please contact vl@samba.org
7744 ****************************************************************************/
7746 void reply_readbs(struct smb_request *req)
7748 START_PROFILE(SMBreadBs);
7749 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7750 END_PROFILE(SMBreadBs);
7754 /****************************************************************************
7755 Reply to a SMBsetattrE.
7756 ****************************************************************************/
7758 void reply_setattrE(struct smb_request *req)
7760 connection_struct *conn = req->conn;
7761 struct smb_file_time ft;
7765 START_PROFILE(SMBsetattrE);
7769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7773 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7775 if(!fsp || (fsp->conn != conn)) {
7776 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7781 * Convert the DOS times into unix times.
7784 ft.atime = convert_time_t_to_timespec(
7785 srv_make_unix_date2(req->vwv+3));
7786 ft.mtime = convert_time_t_to_timespec(
7787 srv_make_unix_date2(req->vwv+5));
7788 ft.create_time = convert_time_t_to_timespec(
7789 srv_make_unix_date2(req->vwv+1));
7791 reply_outbuf(req, 0, 0);
7794 * Patch from Ray Frush <frush@engr.colostate.edu>
7795 * Sometimes times are sent as zero - ignore them.
7798 /* Ensure we have a valid stat struct for the source. */
7799 status = vfs_stat_fsp(fsp);
7800 if (!NT_STATUS_IS_OK(status)) {
7801 reply_nterror(req, status);
7805 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7806 if (!NT_STATUS_IS_OK(status)) {
7807 reply_nterror(req, status);
7811 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7814 (unsigned int)ft.atime.tv_sec,
7815 (unsigned int)ft.mtime.tv_sec,
7816 (unsigned int)ft.create_time.tv_sec
7819 END_PROFILE(SMBsetattrE);
7824 /* Back from the dead for OS/2..... JRA. */
7826 /****************************************************************************
7827 Reply to a SMBwritebmpx (write block multiplex primary) request.
7828 Always reply with an error, if someone has a platform really needs this,
7829 please contact vl@samba.org
7830 ****************************************************************************/
7832 void reply_writebmpx(struct smb_request *req)
7834 START_PROFILE(SMBwriteBmpx);
7835 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7836 END_PROFILE(SMBwriteBmpx);
7840 /****************************************************************************
7841 Reply to a SMBwritebs (write block multiplex secondary) request.
7842 Always reply with an error, if someone has a platform really needs this,
7843 please contact vl@samba.org
7844 ****************************************************************************/
7846 void reply_writebs(struct smb_request *req)
7848 START_PROFILE(SMBwriteBs);
7849 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7850 END_PROFILE(SMBwriteBs);
7854 /****************************************************************************
7855 Reply to a SMBgetattrE.
7856 ****************************************************************************/
7858 void reply_getattrE(struct smb_request *req)
7860 connection_struct *conn = req->conn;
7863 struct timespec create_ts;
7865 START_PROFILE(SMBgetattrE);
7868 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7869 END_PROFILE(SMBgetattrE);
7873 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7875 if(!fsp || (fsp->conn != conn)) {
7876 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7877 END_PROFILE(SMBgetattrE);
7881 /* Do an fstat on this file */
7883 reply_nterror(req, map_nt_error_from_unix(errno));
7884 END_PROFILE(SMBgetattrE);
7888 mode = dos_mode(conn, fsp->fsp_name);
7891 * Convert the times into dos times. Set create
7892 * date to be last modify date as UNIX doesn't save
7896 reply_outbuf(req, 11, 0);
7898 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7899 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7900 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7901 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7902 /* Should we check pending modtime here ? JRA */
7903 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7904 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7907 SIVAL(req->outbuf, smb_vwv6, 0);
7908 SIVAL(req->outbuf, smb_vwv8, 0);
7910 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7911 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7912 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7914 SSVAL(req->outbuf,smb_vwv10, mode);
7916 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7918 END_PROFILE(SMBgetattrE);