2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
34 #include "rpc_client/cli_spoolss.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "rpc_server/rpc_ncacn_np.h"
37 #include "libcli/security/security.h"
39 /****************************************************************************
40 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
41 path or anything including wildcards.
42 We're assuming here that '/' is not the second byte in any multibyte char
43 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
45 ****************************************************************************/
47 /* Custom version for processing POSIX paths. */
48 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
50 static NTSTATUS check_path_syntax_internal(char *path,
52 bool *p_last_component_contains_wcard)
56 NTSTATUS ret = NT_STATUS_OK;
57 bool start_of_name_component = True;
58 bool stream_started = false;
60 *p_last_component_contains_wcard = False;
67 return NT_STATUS_OBJECT_NAME_INVALID;
70 return NT_STATUS_OBJECT_NAME_INVALID;
72 if (strchr_m(&s[1], ':')) {
73 return NT_STATUS_OBJECT_NAME_INVALID;
79 if ((*s == ':') && !posix_path && !stream_started) {
80 if (*p_last_component_contains_wcard) {
81 return NT_STATUS_OBJECT_NAME_INVALID;
83 /* Stream names allow more characters than file names.
84 We're overloading posix_path here to allow a wider
85 range of characters. If stream_started is true this
86 is still a Windows path even if posix_path is true.
89 stream_started = true;
90 start_of_name_component = false;
94 return NT_STATUS_OBJECT_NAME_INVALID;
98 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
100 * Safe to assume is not the second part of a mb char
101 * as this is handled below.
103 /* Eat multiple '/' or '\\' */
104 while (IS_PATH_SEP(*s,posix_path)) {
107 if ((d != path) && (*s != '\0')) {
108 /* We only care about non-leading or trailing '/' or '\\' */
112 start_of_name_component = True;
114 *p_last_component_contains_wcard = False;
118 if (start_of_name_component) {
119 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
120 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
123 * No mb char starts with '.' so we're safe checking the directory separator here.
126 /* If we just added a '/' - delete it */
127 if ((d > path) && (*(d-1) == '/')) {
132 /* Are we at the start ? Can't go back further if so. */
134 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
137 /* Go back one level... */
138 /* We know this is safe as '/' cannot be part of a mb sequence. */
139 /* NOTE - if this assumption is invalid we are not in good shape... */
140 /* Decrement d first as d points to the *next* char to write into. */
141 for (d--; d > path; d--) {
145 s += 2; /* Else go past the .. */
146 /* We're still at the start of a name component, just the previous one. */
149 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
161 if (*s <= 0x1f || *s == '|') {
162 return NT_STATUS_OBJECT_NAME_INVALID;
170 *p_last_component_contains_wcard = True;
179 /* Get the size of the next MB character. */
180 next_codepoint(s,&siz);
198 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
200 return NT_STATUS_INVALID_PARAMETER;
203 start_of_name_component = False;
211 /****************************************************************************
212 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
213 No wildcards allowed.
214 ****************************************************************************/
216 NTSTATUS check_path_syntax(char *path)
219 return check_path_syntax_internal(path, False, &ignore);
222 /****************************************************************************
223 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
224 Wildcards allowed - p_contains_wcard returns true if the last component contained
226 ****************************************************************************/
228 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
230 return check_path_syntax_internal(path, False, p_contains_wcard);
233 /****************************************************************************
234 Check the path for a POSIX client.
235 We're assuming here that '/' is not the second byte in any multibyte char
236 set (a safe assumption).
237 ****************************************************************************/
239 NTSTATUS check_path_syntax_posix(char *path)
242 return check_path_syntax_internal(path, True, &ignore);
245 /****************************************************************************
246 Pull a string and check the path allowing a wilcard - provide for error return.
247 ****************************************************************************/
249 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
250 const char *base_ptr,
257 bool *contains_wcard)
263 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
267 *err = NT_STATUS_INVALID_PARAMETER;
271 *contains_wcard = False;
273 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
275 * For a DFS path the function parse_dfs_path()
276 * will do the path processing, just make a copy.
282 if (lp_posix_pathnames()) {
283 *err = check_path_syntax_posix(*pp_dest);
285 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
291 /****************************************************************************
292 Pull a string and check the path - provide for error return.
293 ****************************************************************************/
295 size_t srvstr_get_path(TALLOC_CTX *ctx,
296 const char *base_ptr,
305 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
306 src_len, flags, err, &ignore);
309 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
310 char **pp_dest, const char *src, int flags,
311 NTSTATUS *err, bool *contains_wcard)
313 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
314 pp_dest, src, smbreq_bufrem(req, src),
315 flags, err, contains_wcard);
318 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
319 char **pp_dest, const char *src, int flags,
323 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
324 flags, err, &ignore);
327 /****************************************************************************
328 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
329 ****************************************************************************/
331 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
334 if ((fsp == NULL) || (conn == NULL)) {
335 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
338 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
339 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
345 /****************************************************************************
346 Check if we have a correct fsp pointing to a file.
347 ****************************************************************************/
349 bool check_fsp(connection_struct *conn, struct smb_request *req,
352 if (!check_fsp_open(conn, req, fsp)) {
355 if (fsp->is_directory) {
356 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
359 if (fsp->fh->fd == -1) {
360 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
363 fsp->num_smb_operations++;
367 /****************************************************************************
368 Check if we have a correct fsp pointing to a quota fake file. Replacement for
369 the CHECK_NTQUOTA_HANDLE_OK macro.
370 ****************************************************************************/
372 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
375 if (!check_fsp_open(conn, req, fsp)) {
379 if (fsp->is_directory) {
383 if (fsp->fake_file_handle == NULL) {
387 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
391 if (fsp->fake_file_handle->private_data == NULL) {
398 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
399 const char *name, int name_type)
402 char *trim_name_type;
403 const char *retarget_parm;
406 int retarget_type = 0x20;
407 int retarget_port = 139;
408 struct sockaddr_storage retarget_addr;
409 struct sockaddr_in *in_addr;
413 if (get_socket_port(sconn->sock) != 139) {
417 trim_name = talloc_strdup(talloc_tos(), name);
418 if (trim_name == NULL) {
421 trim_char(trim_name, ' ', ' ');
423 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
425 if (trim_name_type == NULL) {
429 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
430 trim_name_type, NULL);
431 if (retarget_parm == NULL) {
432 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
435 if (retarget_parm == NULL) {
439 retarget = talloc_strdup(trim_name, retarget_parm);
440 if (retarget == NULL) {
444 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
446 p = strchr(retarget, ':');
449 retarget_port = atoi(p);
452 p = strchr_m(retarget, '#');
455 sscanf(p, "%x", &retarget_type);
458 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
460 DEBUG(10, ("could not resolve %s\n", retarget));
464 if (retarget_addr.ss_family != AF_INET) {
465 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
469 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
471 _smb_setlen(outbuf, 6);
472 SCVAL(outbuf, 0, 0x84);
473 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
474 *(uint16_t *)(outbuf+8) = htons(retarget_port);
476 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
478 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
484 TALLOC_FREE(trim_name);
488 /****************************************************************************
489 Reply to a (netbios-level) special message.
490 ****************************************************************************/
492 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
494 int msg_type = CVAL(inbuf,0);
495 int msg_flags = CVAL(inbuf,1);
497 * We only really use 4 bytes of the outbuf, but for the smb_setlen
498 * calculation & friends (srv_send_smb uses that) we need the full smb
501 char outbuf[smb_size];
503 memset(outbuf, '\0', sizeof(outbuf));
505 smb_setlen(outbuf,0);
508 case 0x81: /* session request */
510 /* inbuf_size is guarenteed to be at least 4. */
512 int name_type1, name_type2;
513 int name_len1, name_len2;
517 if (sconn->nbt.got_session) {
518 exit_server_cleanly("multiple session request not permitted");
521 SCVAL(outbuf,0,0x82);
524 /* inbuf_size is guaranteed to be at least 4. */
525 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
526 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
527 DEBUG(0,("Invalid name length in session request\n"));
530 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
531 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
532 DEBUG(0,("Invalid name length in session request\n"));
536 name_type1 = name_extract((unsigned char *)inbuf,
537 inbuf_size,(unsigned int)4,name1);
538 name_type2 = name_extract((unsigned char *)inbuf,
539 inbuf_size,(unsigned int)(4 + name_len1),name2);
541 if (name_type1 == -1 || name_type2 == -1) {
542 DEBUG(0,("Invalid name type in session request\n"));
546 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
547 name1, name_type1, name2, name_type2));
549 if (netbios_session_retarget(sconn, name1, name_type1)) {
550 exit_server_cleanly("retargeted client");
554 * Windows NT/2k uses "*SMBSERVER" and XP uses
555 * "*SMBSERV" arrggg!!!
557 if (strequal(name1, "*SMBSERVER ")
558 || strequal(name1, "*SMBSERV ")) {
559 fstrcpy(name1, sconn->client_id.addr);
562 set_local_machine_name(name1, True);
563 set_remote_machine_name(name2, True);
565 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
566 get_local_machine_name(), get_remote_machine_name(),
569 if (name_type2 == 'R') {
570 /* We are being asked for a pathworks session ---
572 SCVAL(outbuf, 0,0x83);
576 /* only add the client's machine name to the list
577 of possibly valid usernames if we are operating
578 in share mode security */
579 if (lp_security() == SEC_SHARE) {
580 add_session_user(sconn, get_remote_machine_name());
583 reload_services(sconn->msg_ctx, sconn->sock, True);
586 sconn->nbt.got_session = true;
590 case 0x89: /* session keepalive request
591 (some old clients produce this?) */
592 SCVAL(outbuf,0,SMBkeepalive);
596 case 0x82: /* positive session response */
597 case 0x83: /* negative session response */
598 case 0x84: /* retarget session response */
599 DEBUG(0,("Unexpected session response\n"));
602 case SMBkeepalive: /* session keepalive */
607 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
608 msg_type, msg_flags));
610 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
614 /****************************************************************************
616 conn POINTER CAN BE NULL HERE !
617 ****************************************************************************/
619 void reply_tcon(struct smb_request *req)
621 connection_struct *conn = req->conn;
623 char *service_buf = NULL;
624 char *password = NULL;
629 DATA_BLOB password_blob;
630 TALLOC_CTX *ctx = talloc_tos();
631 struct smbd_server_connection *sconn = req->sconn;
633 START_PROFILE(SMBtcon);
635 if (req->buflen < 4) {
636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
637 END_PROFILE(SMBtcon);
641 p = (const char *)req->buf + 1;
642 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
644 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
646 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
649 if (service_buf == NULL || password == NULL || dev == NULL) {
650 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
651 END_PROFILE(SMBtcon);
654 p = strrchr_m(service_buf,'\\');
658 service = service_buf;
661 password_blob = data_blob(password, pwlen+1);
663 conn = make_connection(sconn,service,password_blob,dev,
664 req->vuid,&nt_status);
667 data_blob_clear_free(&password_blob);
670 reply_nterror(req, nt_status);
671 END_PROFILE(SMBtcon);
675 reply_outbuf(req, 2, 0);
676 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
677 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
678 SSVAL(req->outbuf,smb_tid,conn->cnum);
680 DEBUG(3,("tcon service=%s cnum=%d\n",
681 service, conn->cnum));
683 END_PROFILE(SMBtcon);
687 /****************************************************************************
688 Reply to a tcon and X.
689 conn POINTER CAN BE NULL HERE !
690 ****************************************************************************/
692 void reply_tcon_and_X(struct smb_request *req)
694 connection_struct *conn = req->conn;
695 const char *service = NULL;
697 TALLOC_CTX *ctx = talloc_tos();
698 /* what the cleint thinks the device is */
699 char *client_devicetype = NULL;
700 /* what the server tells the client the share represents */
701 const char *server_devicetype;
707 struct smbd_server_connection *sconn = req->sconn;
709 START_PROFILE(SMBtconX);
712 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
713 END_PROFILE(SMBtconX);
717 passlen = SVAL(req->vwv+3, 0);
718 tcon_flags = SVAL(req->vwv+2, 0);
720 /* we might have to close an old one */
721 if ((tcon_flags & 0x1) && conn) {
722 close_cnum(conn,req->vuid);
727 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
728 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
729 END_PROFILE(SMBtconX);
733 if (sconn->smb1.negprot.encrypted_passwords) {
734 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
735 if (lp_security() == SEC_SHARE) {
737 * Security = share always has a pad byte
738 * after the password.
740 p = (const char *)req->buf + passlen + 1;
742 p = (const char *)req->buf + passlen;
745 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
746 /* Ensure correct termination */
747 password.data[passlen]=0;
748 p = (const char *)req->buf + passlen + 1;
751 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
754 data_blob_clear_free(&password);
755 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
756 END_PROFILE(SMBtconX);
761 * the service name can be either: \\server\share
762 * or share directly like on the DELL PowerVault 705
765 q = strchr_m(path+2,'\\');
767 data_blob_clear_free(&password);
768 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
769 END_PROFILE(SMBtconX);
777 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
778 &client_devicetype, p,
779 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
781 if (client_devicetype == NULL) {
782 data_blob_clear_free(&password);
783 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
784 END_PROFILE(SMBtconX);
788 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
790 conn = make_connection(sconn, service, password, client_devicetype,
791 req->vuid, &nt_status);
794 data_blob_clear_free(&password);
797 reply_nterror(req, nt_status);
798 END_PROFILE(SMBtconX);
803 server_devicetype = "IPC";
804 else if ( IS_PRINT(conn) )
805 server_devicetype = "LPT1:";
807 server_devicetype = "A:";
809 if (get_Protocol() < PROTOCOL_NT1) {
810 reply_outbuf(req, 2, 0);
811 if (message_push_string(&req->outbuf, server_devicetype,
812 STR_TERMINATE|STR_ASCII) == -1) {
813 reply_nterror(req, NT_STATUS_NO_MEMORY);
814 END_PROFILE(SMBtconX);
818 /* NT sets the fstype of IPC$ to the null string */
819 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
821 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
822 /* Return permissions. */
826 reply_outbuf(req, 7, 0);
829 perm1 = FILE_ALL_ACCESS;
830 perm2 = FILE_ALL_ACCESS;
832 perm1 = CAN_WRITE(conn) ?
837 SIVAL(req->outbuf, smb_vwv3, perm1);
838 SIVAL(req->outbuf, smb_vwv5, perm2);
840 reply_outbuf(req, 3, 0);
843 if ((message_push_string(&req->outbuf, server_devicetype,
844 STR_TERMINATE|STR_ASCII) == -1)
845 || (message_push_string(&req->outbuf, fstype,
846 STR_TERMINATE) == -1)) {
847 reply_nterror(req, NT_STATUS_NO_MEMORY);
848 END_PROFILE(SMBtconX);
852 /* what does setting this bit do? It is set by NT4 and
853 may affect the ability to autorun mounted cdroms */
854 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
855 (lp_csc_policy(SNUM(conn)) << 2));
857 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
858 DEBUG(2,("Serving %s as a Dfs root\n",
859 lp_servicename(SNUM(conn)) ));
860 SSVAL(req->outbuf, smb_vwv2,
861 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
866 DEBUG(3,("tconX service=%s \n",
869 /* set the incoming and outgoing tid to the just created one */
870 SSVAL(req->inbuf,smb_tid,conn->cnum);
871 SSVAL(req->outbuf,smb_tid,conn->cnum);
873 END_PROFILE(SMBtconX);
875 req->tid = conn->cnum;
880 /****************************************************************************
881 Reply to an unknown type.
882 ****************************************************************************/
884 void reply_unknown_new(struct smb_request *req, uint8 type)
886 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
887 smb_fn_name(type), type, type));
888 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
892 /****************************************************************************
894 conn POINTER CAN BE NULL HERE !
895 ****************************************************************************/
897 void reply_ioctl(struct smb_request *req)
899 connection_struct *conn = req->conn;
906 START_PROFILE(SMBioctl);
909 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
910 END_PROFILE(SMBioctl);
914 device = SVAL(req->vwv+1, 0);
915 function = SVAL(req->vwv+2, 0);
916 ioctl_code = (device << 16) + function;
918 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
920 switch (ioctl_code) {
921 case IOCTL_QUERY_JOB_INFO:
925 reply_force_doserror(req, ERRSRV, ERRnosupport);
926 END_PROFILE(SMBioctl);
930 reply_outbuf(req, 8, replysize+1);
931 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
932 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
933 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
934 p = smb_buf(req->outbuf);
935 memset(p, '\0', replysize+1); /* valgrind-safe. */
936 p += 1; /* Allow for alignment */
938 switch (ioctl_code) {
939 case IOCTL_QUERY_JOB_INFO:
941 files_struct *fsp = file_fsp(
942 req, SVAL(req->vwv+0, 0));
944 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
945 END_PROFILE(SMBioctl);
949 if (fsp->print_file) {
950 SSVAL(p, 0, fsp->print_file->rap_jobid);
954 srvstr_push((char *)req->outbuf, req->flags2, p+2,
956 STR_TERMINATE|STR_ASCII);
958 srvstr_push((char *)req->outbuf, req->flags2,
959 p+18, lp_servicename(SNUM(conn)),
960 13, STR_TERMINATE|STR_ASCII);
968 END_PROFILE(SMBioctl);
972 /****************************************************************************
973 Strange checkpath NTSTATUS mapping.
974 ****************************************************************************/
976 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
978 /* Strange DOS error code semantics only for checkpath... */
979 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
980 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
981 /* We need to map to ERRbadpath */
982 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
988 /****************************************************************************
989 Reply to a checkpath.
990 ****************************************************************************/
992 void reply_checkpath(struct smb_request *req)
994 connection_struct *conn = req->conn;
995 struct smb_filename *smb_fname = NULL;
998 TALLOC_CTX *ctx = talloc_tos();
1000 START_PROFILE(SMBcheckpath);
1002 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1003 STR_TERMINATE, &status);
1005 if (!NT_STATUS_IS_OK(status)) {
1006 status = map_checkpath_error(req->flags2, status);
1007 reply_nterror(req, status);
1008 END_PROFILE(SMBcheckpath);
1012 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1014 status = filename_convert(ctx,
1016 req->flags2 & FLAGS2_DFS_PATHNAMES,
1022 if (!NT_STATUS_IS_OK(status)) {
1023 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1024 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1025 ERRSRV, ERRbadpath);
1026 END_PROFILE(SMBcheckpath);
1032 if (!VALID_STAT(smb_fname->st) &&
1033 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1034 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1035 smb_fname_str_dbg(smb_fname), strerror(errno)));
1036 status = map_nt_error_from_unix(errno);
1040 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1041 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1042 ERRDOS, ERRbadpath);
1046 reply_outbuf(req, 0, 0);
1049 /* We special case this - as when a Windows machine
1050 is parsing a path is steps through the components
1051 one at a time - if a component fails it expects
1052 ERRbadpath, not ERRbadfile.
1054 status = map_checkpath_error(req->flags2, status);
1055 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1057 * Windows returns different error codes if
1058 * the parent directory is valid but not the
1059 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1060 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1061 * if the path is invalid.
1063 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1064 ERRDOS, ERRbadpath);
1068 reply_nterror(req, status);
1071 TALLOC_FREE(smb_fname);
1072 END_PROFILE(SMBcheckpath);
1076 /****************************************************************************
1078 ****************************************************************************/
1080 void reply_getatr(struct smb_request *req)
1082 connection_struct *conn = req->conn;
1083 struct smb_filename *smb_fname = NULL;
1090 TALLOC_CTX *ctx = talloc_tos();
1091 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1093 START_PROFILE(SMBgetatr);
1095 p = (const char *)req->buf + 1;
1096 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1097 if (!NT_STATUS_IS_OK(status)) {
1098 reply_nterror(req, status);
1102 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1103 under WfWg - weird! */
1104 if (*fname == '\0') {
1105 mode = aHIDDEN | aDIR;
1106 if (!CAN_WRITE(conn)) {
1112 status = filename_convert(ctx,
1114 req->flags2 & FLAGS2_DFS_PATHNAMES,
1119 if (!NT_STATUS_IS_OK(status)) {
1120 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1121 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1122 ERRSRV, ERRbadpath);
1125 reply_nterror(req, status);
1128 if (!VALID_STAT(smb_fname->st) &&
1129 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1130 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1131 smb_fname_str_dbg(smb_fname),
1133 reply_nterror(req, map_nt_error_from_unix(errno));
1137 mode = dos_mode(conn, smb_fname);
1138 size = smb_fname->st.st_ex_size;
1140 if (ask_sharemode) {
1141 struct timespec write_time_ts;
1142 struct file_id fileid;
1144 ZERO_STRUCT(write_time_ts);
1145 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1146 get_file_infos(fileid, 0, NULL, &write_time_ts);
1147 if (!null_timespec(write_time_ts)) {
1148 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1152 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1158 reply_outbuf(req, 10, 0);
1160 SSVAL(req->outbuf,smb_vwv0,mode);
1161 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1162 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1164 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1166 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1168 if (get_Protocol() >= PROTOCOL_NT1) {
1169 SSVAL(req->outbuf, smb_flg2,
1170 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1173 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1174 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1177 TALLOC_FREE(smb_fname);
1179 END_PROFILE(SMBgetatr);
1183 /****************************************************************************
1185 ****************************************************************************/
1187 void reply_setatr(struct smb_request *req)
1189 struct smb_file_time ft;
1190 connection_struct *conn = req->conn;
1191 struct smb_filename *smb_fname = NULL;
1197 TALLOC_CTX *ctx = talloc_tos();
1199 START_PROFILE(SMBsetatr);
1204 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1208 p = (const char *)req->buf + 1;
1209 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1210 if (!NT_STATUS_IS_OK(status)) {
1211 reply_nterror(req, status);
1215 status = filename_convert(ctx,
1217 req->flags2 & FLAGS2_DFS_PATHNAMES,
1222 if (!NT_STATUS_IS_OK(status)) {
1223 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1224 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1225 ERRSRV, ERRbadpath);
1228 reply_nterror(req, status);
1232 if (smb_fname->base_name[0] == '.' &&
1233 smb_fname->base_name[1] == '\0') {
1235 * Not sure here is the right place to catch this
1236 * condition. Might be moved to somewhere else later -- vl
1238 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1242 mode = SVAL(req->vwv+0, 0);
1243 mtime = srv_make_unix_date3(req->vwv+1);
1245 ft.mtime = convert_time_t_to_timespec(mtime);
1246 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1247 if (!NT_STATUS_IS_OK(status)) {
1248 reply_nterror(req, status);
1252 if (mode != FILE_ATTRIBUTE_NORMAL) {
1253 if (VALID_STAT_OF_DIR(smb_fname->st))
1258 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1260 reply_nterror(req, map_nt_error_from_unix(errno));
1265 reply_outbuf(req, 0, 0);
1267 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1270 TALLOC_FREE(smb_fname);
1271 END_PROFILE(SMBsetatr);
1275 /****************************************************************************
1277 ****************************************************************************/
1279 void reply_dskattr(struct smb_request *req)
1281 connection_struct *conn = req->conn;
1282 uint64_t dfree,dsize,bsize;
1283 START_PROFILE(SMBdskattr);
1285 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1286 reply_nterror(req, map_nt_error_from_unix(errno));
1287 END_PROFILE(SMBdskattr);
1291 reply_outbuf(req, 5, 0);
1293 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1294 double total_space, free_space;
1295 /* we need to scale this to a number that DOS6 can handle. We
1296 use floating point so we can handle large drives on systems
1297 that don't have 64 bit integers
1299 we end up displaying a maximum of 2G to DOS systems
1301 total_space = dsize * (double)bsize;
1302 free_space = dfree * (double)bsize;
1304 dsize = (uint64_t)((total_space+63*512) / (64*512));
1305 dfree = (uint64_t)((free_space+63*512) / (64*512));
1307 if (dsize > 0xFFFF) dsize = 0xFFFF;
1308 if (dfree > 0xFFFF) dfree = 0xFFFF;
1310 SSVAL(req->outbuf,smb_vwv0,dsize);
1311 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1312 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1313 SSVAL(req->outbuf,smb_vwv3,dfree);
1315 SSVAL(req->outbuf,smb_vwv0,dsize);
1316 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1317 SSVAL(req->outbuf,smb_vwv2,512);
1318 SSVAL(req->outbuf,smb_vwv3,dfree);
1321 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1323 END_PROFILE(SMBdskattr);
1328 * Utility function to split the filename from the directory.
1330 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1331 char **fname_dir_out,
1332 char **fname_mask_out)
1334 const char *p = NULL;
1335 char *fname_dir = NULL;
1336 char *fname_mask = NULL;
1338 p = strrchr_m(fname_in, '/');
1340 fname_dir = talloc_strdup(ctx, ".");
1341 fname_mask = talloc_strdup(ctx, fname_in);
1343 fname_dir = talloc_strndup(ctx, fname_in,
1344 PTR_DIFF(p, fname_in));
1345 fname_mask = talloc_strdup(ctx, p+1);
1348 if (!fname_dir || !fname_mask) {
1349 TALLOC_FREE(fname_dir);
1350 TALLOC_FREE(fname_mask);
1351 return NT_STATUS_NO_MEMORY;
1354 *fname_dir_out = fname_dir;
1355 *fname_mask_out = fname_mask;
1356 return NT_STATUS_OK;
1359 /****************************************************************************
1361 Can be called from SMBsearch, SMBffirst or SMBfunique.
1362 ****************************************************************************/
1364 void reply_search(struct smb_request *req)
1366 connection_struct *conn = req->conn;
1368 const char *mask = NULL;
1369 char *directory = NULL;
1370 struct smb_filename *smb_fname = NULL;
1374 struct timespec date;
1376 unsigned int numentries = 0;
1377 unsigned int maxentries = 0;
1378 bool finished = False;
1383 bool check_descend = False;
1384 bool expect_close = False;
1386 bool mask_contains_wcard = False;
1387 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1388 TALLOC_CTX *ctx = talloc_tos();
1389 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1390 struct dptr_struct *dirptr = NULL;
1391 struct smbd_server_connection *sconn = req->sconn;
1393 START_PROFILE(SMBsearch);
1396 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1400 if (lp_posix_pathnames()) {
1401 reply_unknown_new(req, req->cmd);
1405 /* If we were called as SMBffirst then we must expect close. */
1406 if(req->cmd == SMBffirst) {
1407 expect_close = True;
1410 reply_outbuf(req, 1, 3);
1411 maxentries = SVAL(req->vwv+0, 0);
1412 dirtype = SVAL(req->vwv+1, 0);
1413 p = (const char *)req->buf + 1;
1414 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1415 &nt_status, &mask_contains_wcard);
1416 if (!NT_STATUS_IS_OK(nt_status)) {
1417 reply_nterror(req, nt_status);
1422 status_len = SVAL(p, 0);
1425 /* dirtype &= ~aDIR; */
1427 if (status_len == 0) {
1428 nt_status = filename_convert(ctx, conn,
1429 req->flags2 & FLAGS2_DFS_PATHNAMES,
1431 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1432 &mask_contains_wcard,
1434 if (!NT_STATUS_IS_OK(nt_status)) {
1435 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1436 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1437 ERRSRV, ERRbadpath);
1440 reply_nterror(req, nt_status);
1444 directory = smb_fname->base_name;
1446 p = strrchr_m(directory,'/');
1447 if ((p != NULL) && (*directory != '/')) {
1449 directory = talloc_strndup(ctx, directory,
1450 PTR_DIFF(p, directory));
1453 directory = talloc_strdup(ctx,".");
1457 reply_nterror(req, NT_STATUS_NO_MEMORY);
1461 memset((char *)status,'\0',21);
1462 SCVAL(status,0,(dirtype & 0x1F));
1464 nt_status = dptr_create(conn,
1471 mask_contains_wcard,
1474 if (!NT_STATUS_IS_OK(nt_status)) {
1475 reply_nterror(req, nt_status);
1478 dptr_num = dptr_dnum(dirptr);
1481 const char *dirpath;
1483 memcpy(status,p,21);
1484 status_dirtype = CVAL(status,0) & 0x1F;
1485 if (status_dirtype != (dirtype & 0x1F)) {
1486 dirtype = status_dirtype;
1489 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1493 dirpath = dptr_path(sconn, dptr_num);
1494 directory = talloc_strdup(ctx, dirpath);
1496 reply_nterror(req, NT_STATUS_NO_MEMORY);
1500 mask = dptr_wcard(sconn, dptr_num);
1505 * For a 'continue' search we have no string. So
1506 * check from the initial saved string.
1508 mask_contains_wcard = ms_has_wild(mask);
1509 dirtype = dptr_attr(sconn, dptr_num);
1512 DEBUG(4,("dptr_num is %d\n",dptr_num));
1514 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1515 dptr_init_search_op(dirptr);
1517 if ((dirtype&0x1F) == aVOLID) {
1518 char buf[DIR_STRUCT_SIZE];
1519 memcpy(buf,status,21);
1520 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1521 0,aVOLID,0,!allow_long_path_components)) {
1522 reply_nterror(req, NT_STATUS_NO_MEMORY);
1525 dptr_fill(sconn, buf+12,dptr_num);
1526 if (dptr_zero(buf+12) && (status_len==0)) {
1531 if (message_push_blob(&req->outbuf,
1532 data_blob_const(buf, sizeof(buf)))
1534 reply_nterror(req, NT_STATUS_NO_MEMORY);
1542 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1545 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1546 directory,lp_dontdescend(SNUM(conn))));
1547 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1548 check_descend = True;
1551 for (i=numentries;(i<maxentries) && !finished;i++) {
1552 finished = !get_dir_entry(ctx,
1563 char buf[DIR_STRUCT_SIZE];
1564 memcpy(buf,status,21);
1565 if (!make_dir_struct(ctx,
1571 convert_timespec_to_time_t(date),
1572 !allow_long_path_components)) {
1573 reply_nterror(req, NT_STATUS_NO_MEMORY);
1576 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1579 if (message_push_blob(&req->outbuf,
1580 data_blob_const(buf, sizeof(buf)))
1582 reply_nterror(req, NT_STATUS_NO_MEMORY);
1592 /* If we were called as SMBffirst with smb_search_id == NULL
1593 and no entries were found then return error and close dirptr
1596 if (numentries == 0) {
1597 dptr_close(sconn, &dptr_num);
1598 } else if(expect_close && status_len == 0) {
1599 /* Close the dptr - we know it's gone */
1600 dptr_close(sconn, &dptr_num);
1603 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1604 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1605 dptr_close(sconn, &dptr_num);
1608 if ((numentries == 0) && !mask_contains_wcard) {
1609 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1613 SSVAL(req->outbuf,smb_vwv0,numentries);
1614 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1615 SCVAL(smb_buf(req->outbuf),0,5);
1616 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1618 /* The replies here are never long name. */
1619 SSVAL(req->outbuf, smb_flg2,
1620 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1621 if (!allow_long_path_components) {
1622 SSVAL(req->outbuf, smb_flg2,
1623 SVAL(req->outbuf, smb_flg2)
1624 & (~FLAGS2_LONG_PATH_COMPONENTS));
1627 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1628 SSVAL(req->outbuf, smb_flg2,
1629 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1631 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1632 smb_fn_name(req->cmd),
1639 TALLOC_FREE(directory);
1640 TALLOC_FREE(smb_fname);
1641 END_PROFILE(SMBsearch);
1645 /****************************************************************************
1646 Reply to a fclose (stop directory search).
1647 ****************************************************************************/
1649 void reply_fclose(struct smb_request *req)
1657 bool path_contains_wcard = False;
1658 TALLOC_CTX *ctx = talloc_tos();
1659 struct smbd_server_connection *sconn = req->sconn;
1661 START_PROFILE(SMBfclose);
1663 if (lp_posix_pathnames()) {
1664 reply_unknown_new(req, req->cmd);
1665 END_PROFILE(SMBfclose);
1669 p = (const char *)req->buf + 1;
1670 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1671 &err, &path_contains_wcard);
1672 if (!NT_STATUS_IS_OK(err)) {
1673 reply_nterror(req, err);
1674 END_PROFILE(SMBfclose);
1678 status_len = SVAL(p,0);
1681 if (status_len == 0) {
1682 reply_force_doserror(req, ERRSRV, ERRsrverror);
1683 END_PROFILE(SMBfclose);
1687 memcpy(status,p,21);
1689 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1690 /* Close the dptr - we know it's gone */
1691 dptr_close(sconn, &dptr_num);
1694 reply_outbuf(req, 1, 0);
1695 SSVAL(req->outbuf,smb_vwv0,0);
1697 DEBUG(3,("search close\n"));
1699 END_PROFILE(SMBfclose);
1703 /****************************************************************************
1705 ****************************************************************************/
1707 void reply_open(struct smb_request *req)
1709 connection_struct *conn = req->conn;
1710 struct smb_filename *smb_fname = NULL;
1722 uint32 create_disposition;
1723 uint32 create_options = 0;
1724 uint32_t private_flags = 0;
1726 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1727 TALLOC_CTX *ctx = talloc_tos();
1729 START_PROFILE(SMBopen);
1732 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1736 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1737 deny_mode = SVAL(req->vwv+0, 0);
1738 dos_attr = SVAL(req->vwv+1, 0);
1740 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1741 STR_TERMINATE, &status);
1742 if (!NT_STATUS_IS_OK(status)) {
1743 reply_nterror(req, status);
1747 status = filename_convert(ctx,
1749 req->flags2 & FLAGS2_DFS_PATHNAMES,
1754 if (!NT_STATUS_IS_OK(status)) {
1755 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1756 reply_botherror(req,
1757 NT_STATUS_PATH_NOT_COVERED,
1758 ERRSRV, ERRbadpath);
1761 reply_nterror(req, status);
1765 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1766 OPENX_FILE_EXISTS_OPEN, &access_mask,
1767 &share_mode, &create_disposition,
1768 &create_options, &private_flags)) {
1769 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1773 status = SMB_VFS_CREATE_FILE(
1776 0, /* root_dir_fid */
1777 smb_fname, /* fname */
1778 access_mask, /* access_mask */
1779 share_mode, /* share_access */
1780 create_disposition, /* create_disposition*/
1781 create_options, /* create_options */
1782 dos_attr, /* file_attributes */
1783 oplock_request, /* oplock_request */
1784 0, /* allocation_size */
1791 if (!NT_STATUS_IS_OK(status)) {
1792 if (open_was_deferred(req->mid)) {
1793 /* We have re-scheduled this call. */
1796 reply_openerror(req, status);
1800 size = smb_fname->st.st_ex_size;
1801 fattr = dos_mode(conn, smb_fname);
1803 /* Deal with other possible opens having a modified
1805 if (ask_sharemode) {
1806 struct timespec write_time_ts;
1808 ZERO_STRUCT(write_time_ts);
1809 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1810 if (!null_timespec(write_time_ts)) {
1811 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1815 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1818 DEBUG(3,("attempt to open a directory %s\n",
1820 close_file(req, fsp, ERROR_CLOSE);
1821 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1822 ERRDOS, ERRnoaccess);
1826 reply_outbuf(req, 7, 0);
1827 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1828 SSVAL(req->outbuf,smb_vwv1,fattr);
1829 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1830 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1832 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1834 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1835 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1837 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1838 SCVAL(req->outbuf,smb_flg,
1839 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1842 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1843 SCVAL(req->outbuf,smb_flg,
1844 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1847 TALLOC_FREE(smb_fname);
1848 END_PROFILE(SMBopen);
1852 /****************************************************************************
1853 Reply to an open and X.
1854 ****************************************************************************/
1856 void reply_open_and_X(struct smb_request *req)
1858 connection_struct *conn = req->conn;
1859 struct smb_filename *smb_fname = NULL;
1864 /* Breakout the oplock request bits so we can set the
1865 reply bits separately. */
1866 int ex_oplock_request;
1867 int core_oplock_request;
1870 int smb_sattr = SVAL(req->vwv+4, 0);
1871 uint32 smb_time = make_unix_date3(req->vwv+6);
1879 uint64_t allocation_size;
1880 ssize_t retval = -1;
1883 uint32 create_disposition;
1884 uint32 create_options = 0;
1885 uint32_t private_flags = 0;
1886 TALLOC_CTX *ctx = talloc_tos();
1888 START_PROFILE(SMBopenX);
1890 if (req->wct < 15) {
1891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1895 open_flags = SVAL(req->vwv+2, 0);
1896 deny_mode = SVAL(req->vwv+3, 0);
1897 smb_attr = SVAL(req->vwv+5, 0);
1898 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1899 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1900 oplock_request = ex_oplock_request | core_oplock_request;
1901 smb_ofun = SVAL(req->vwv+8, 0);
1902 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1904 /* If it's an IPC, pass off the pipe handler. */
1906 if (lp_nt_pipe_support()) {
1907 reply_open_pipe_and_X(conn, req);
1909 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1914 /* XXXX we need to handle passed times, sattr and flags */
1915 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1916 STR_TERMINATE, &status);
1917 if (!NT_STATUS_IS_OK(status)) {
1918 reply_nterror(req, status);
1922 status = filename_convert(ctx,
1924 req->flags2 & FLAGS2_DFS_PATHNAMES,
1929 if (!NT_STATUS_IS_OK(status)) {
1930 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1931 reply_botherror(req,
1932 NT_STATUS_PATH_NOT_COVERED,
1933 ERRSRV, ERRbadpath);
1936 reply_nterror(req, status);
1940 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1941 &access_mask, &share_mode,
1942 &create_disposition,
1945 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1949 status = SMB_VFS_CREATE_FILE(
1952 0, /* root_dir_fid */
1953 smb_fname, /* fname */
1954 access_mask, /* access_mask */
1955 share_mode, /* share_access */
1956 create_disposition, /* create_disposition*/
1957 create_options, /* create_options */
1958 smb_attr, /* file_attributes */
1959 oplock_request, /* oplock_request */
1960 0, /* allocation_size */
1965 &smb_action); /* pinfo */
1967 if (!NT_STATUS_IS_OK(status)) {
1968 if (open_was_deferred(req->mid)) {
1969 /* We have re-scheduled this call. */
1972 reply_openerror(req, status);
1976 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1977 if the file is truncated or created. */
1978 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1979 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1980 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1981 close_file(req, fsp, ERROR_CLOSE);
1982 reply_nterror(req, NT_STATUS_DISK_FULL);
1985 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1987 close_file(req, fsp, ERROR_CLOSE);
1988 reply_nterror(req, NT_STATUS_DISK_FULL);
1991 status = vfs_stat_fsp(fsp);
1992 if (!NT_STATUS_IS_OK(status)) {
1993 close_file(req, fsp, ERROR_CLOSE);
1994 reply_nterror(req, status);
1999 fattr = dos_mode(conn, fsp->fsp_name);
2000 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2002 close_file(req, fsp, ERROR_CLOSE);
2003 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2007 /* If the caller set the extended oplock request bit
2008 and we granted one (by whatever means) - set the
2009 correct bit for extended oplock reply.
2012 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2013 smb_action |= EXTENDED_OPLOCK_GRANTED;
2016 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2017 smb_action |= EXTENDED_OPLOCK_GRANTED;
2020 /* If the caller set the core oplock request bit
2021 and we granted one (by whatever means) - set the
2022 correct bit for core oplock reply.
2025 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2026 reply_outbuf(req, 19, 0);
2028 reply_outbuf(req, 15, 0);
2031 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2032 SCVAL(req->outbuf, smb_flg,
2033 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2036 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2037 SCVAL(req->outbuf, smb_flg,
2038 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2041 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2042 SSVAL(req->outbuf,smb_vwv3,fattr);
2043 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2044 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2046 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2048 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2049 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2050 SSVAL(req->outbuf,smb_vwv11,smb_action);
2052 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2053 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2058 TALLOC_FREE(smb_fname);
2059 END_PROFILE(SMBopenX);
2063 /****************************************************************************
2064 Reply to a SMBulogoffX.
2065 ****************************************************************************/
2067 void reply_ulogoffX(struct smb_request *req)
2069 struct smbd_server_connection *sconn = req->sconn;
2072 START_PROFILE(SMBulogoffX);
2074 vuser = get_valid_user_struct(sconn, req->vuid);
2077 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2081 /* in user level security we are supposed to close any files
2082 open by this user */
2083 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2084 file_close_user(sconn, req->vuid);
2087 invalidate_vuid(sconn, req->vuid);
2089 reply_outbuf(req, 2, 0);
2091 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2093 END_PROFILE(SMBulogoffX);
2094 req->vuid = UID_FIELD_INVALID;
2098 /****************************************************************************
2099 Reply to a mknew or a create.
2100 ****************************************************************************/
2102 void reply_mknew(struct smb_request *req)
2104 connection_struct *conn = req->conn;
2105 struct smb_filename *smb_fname = NULL;
2108 struct smb_file_time ft;
2110 int oplock_request = 0;
2112 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2113 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2114 uint32 create_disposition;
2115 uint32 create_options = 0;
2116 TALLOC_CTX *ctx = talloc_tos();
2118 START_PROFILE(SMBcreate);
2122 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2126 fattr = SVAL(req->vwv+0, 0);
2127 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2130 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2132 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2133 STR_TERMINATE, &status);
2134 if (!NT_STATUS_IS_OK(status)) {
2135 reply_nterror(req, status);
2139 status = filename_convert(ctx,
2141 req->flags2 & FLAGS2_DFS_PATHNAMES,
2146 if (!NT_STATUS_IS_OK(status)) {
2147 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2148 reply_botherror(req,
2149 NT_STATUS_PATH_NOT_COVERED,
2150 ERRSRV, ERRbadpath);
2153 reply_nterror(req, status);
2157 if (fattr & aVOLID) {
2158 DEBUG(0,("Attempt to create file (%s) with volid set - "
2159 "please report this\n",
2160 smb_fname_str_dbg(smb_fname)));
2163 if(req->cmd == SMBmknew) {
2164 /* We should fail if file exists. */
2165 create_disposition = FILE_CREATE;
2167 /* Create if file doesn't exist, truncate if it does. */
2168 create_disposition = FILE_OVERWRITE_IF;
2171 status = SMB_VFS_CREATE_FILE(
2174 0, /* root_dir_fid */
2175 smb_fname, /* fname */
2176 access_mask, /* access_mask */
2177 share_mode, /* share_access */
2178 create_disposition, /* create_disposition*/
2179 create_options, /* create_options */
2180 fattr, /* file_attributes */
2181 oplock_request, /* oplock_request */
2182 0, /* allocation_size */
2183 0, /* private_flags */
2189 if (!NT_STATUS_IS_OK(status)) {
2190 if (open_was_deferred(req->mid)) {
2191 /* We have re-scheduled this call. */
2194 reply_openerror(req, status);
2198 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2199 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2200 if (!NT_STATUS_IS_OK(status)) {
2201 END_PROFILE(SMBcreate);
2205 reply_outbuf(req, 1, 0);
2206 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2208 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2209 SCVAL(req->outbuf,smb_flg,
2210 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2213 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2214 SCVAL(req->outbuf,smb_flg,
2215 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2218 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2219 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2220 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2221 (unsigned int)fattr));
2224 TALLOC_FREE(smb_fname);
2225 END_PROFILE(SMBcreate);
2229 /****************************************************************************
2230 Reply to a create temporary file.
2231 ****************************************************************************/
2233 void reply_ctemp(struct smb_request *req)
2235 connection_struct *conn = req->conn;
2236 struct smb_filename *smb_fname = NULL;
2244 TALLOC_CTX *ctx = talloc_tos();
2246 START_PROFILE(SMBctemp);
2249 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2253 fattr = SVAL(req->vwv+0, 0);
2254 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2256 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2257 STR_TERMINATE, &status);
2258 if (!NT_STATUS_IS_OK(status)) {
2259 reply_nterror(req, status);
2263 fname = talloc_asprintf(ctx,
2267 fname = talloc_strdup(ctx, "TMXXXXXX");
2271 reply_nterror(req, NT_STATUS_NO_MEMORY);
2275 status = filename_convert(ctx, conn,
2276 req->flags2 & FLAGS2_DFS_PATHNAMES,
2281 if (!NT_STATUS_IS_OK(status)) {
2282 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2283 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2284 ERRSRV, ERRbadpath);
2287 reply_nterror(req, status);
2291 tmpfd = mkstemp(smb_fname->base_name);
2293 reply_nterror(req, map_nt_error_from_unix(errno));
2297 SMB_VFS_STAT(conn, smb_fname);
2299 /* We should fail if file does not exist. */
2300 status = SMB_VFS_CREATE_FILE(
2303 0, /* root_dir_fid */
2304 smb_fname, /* fname */
2305 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2306 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2307 FILE_OPEN, /* create_disposition*/
2308 0, /* create_options */
2309 fattr, /* file_attributes */
2310 oplock_request, /* oplock_request */
2311 0, /* allocation_size */
2312 0, /* private_flags */
2318 /* close fd from mkstemp() */
2321 if (!NT_STATUS_IS_OK(status)) {
2322 if (open_was_deferred(req->mid)) {
2323 /* We have re-scheduled this call. */
2326 reply_openerror(req, status);
2330 reply_outbuf(req, 1, 0);
2331 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2333 /* the returned filename is relative to the directory */
2334 s = strrchr_m(fsp->fsp_name->base_name, '/');
2336 s = fsp->fsp_name->base_name;
2342 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2343 thing in the byte section. JRA */
2344 SSVALS(p, 0, -1); /* what is this? not in spec */
2346 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2348 reply_nterror(req, NT_STATUS_NO_MEMORY);
2352 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2353 SCVAL(req->outbuf, smb_flg,
2354 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2357 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2358 SCVAL(req->outbuf, smb_flg,
2359 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2362 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2363 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2364 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2366 TALLOC_FREE(smb_fname);
2367 END_PROFILE(SMBctemp);
2371 /*******************************************************************
2372 Check if a user is allowed to rename a file.
2373 ********************************************************************/
2375 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2380 if (!CAN_WRITE(conn)) {
2381 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2384 fmode = dos_mode(conn, fsp->fsp_name);
2385 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2386 return NT_STATUS_NO_SUCH_FILE;
2389 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2390 if (fsp->posix_open) {
2391 return NT_STATUS_OK;
2394 /* If no pathnames are open below this
2395 directory, allow the rename. */
2397 if (file_find_subpath(fsp)) {
2398 return NT_STATUS_ACCESS_DENIED;
2400 return NT_STATUS_OK;
2403 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2404 return NT_STATUS_OK;
2407 return NT_STATUS_ACCESS_DENIED;
2410 /*******************************************************************
2411 * unlink a file with all relevant access checks
2412 *******************************************************************/
2414 static NTSTATUS do_unlink(connection_struct *conn,
2415 struct smb_request *req,
2416 struct smb_filename *smb_fname,
2421 uint32 dirtype_orig = dirtype;
2424 bool posix_paths = lp_posix_pathnames();
2426 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2427 smb_fname_str_dbg(smb_fname),
2430 if (!CAN_WRITE(conn)) {
2431 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2435 ret = SMB_VFS_LSTAT(conn, smb_fname);
2437 ret = SMB_VFS_STAT(conn, smb_fname);
2440 return map_nt_error_from_unix(errno);
2443 fattr = dos_mode(conn, smb_fname);
2445 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2446 dirtype = aDIR|aARCH|aRONLY;
2449 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2451 return NT_STATUS_NO_SUCH_FILE;
2454 if (!dir_check_ftype(conn, fattr, dirtype)) {
2456 return NT_STATUS_FILE_IS_A_DIRECTORY;
2458 return NT_STATUS_NO_SUCH_FILE;
2461 if (dirtype_orig & 0x8000) {
2462 /* These will never be set for POSIX. */
2463 return NT_STATUS_NO_SUCH_FILE;
2467 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2468 return NT_STATUS_FILE_IS_A_DIRECTORY;
2471 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2472 return NT_STATUS_NO_SUCH_FILE;
2475 if (dirtype & 0xFF00) {
2476 /* These will never be set for POSIX. */
2477 return NT_STATUS_NO_SUCH_FILE;
2482 return NT_STATUS_NO_SUCH_FILE;
2485 /* Can't delete a directory. */
2487 return NT_STATUS_FILE_IS_A_DIRECTORY;
2492 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2493 return NT_STATUS_OBJECT_NAME_INVALID;
2494 #endif /* JRATEST */
2496 /* On open checks the open itself will check the share mode, so
2497 don't do it here as we'll get it wrong. */
2499 status = SMB_VFS_CREATE_FILE
2502 0, /* root_dir_fid */
2503 smb_fname, /* fname */
2504 DELETE_ACCESS, /* access_mask */
2505 FILE_SHARE_NONE, /* share_access */
2506 FILE_OPEN, /* create_disposition*/
2507 FILE_NON_DIRECTORY_FILE, /* create_options */
2508 /* file_attributes */
2509 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2510 FILE_ATTRIBUTE_NORMAL,
2511 0, /* oplock_request */
2512 0, /* allocation_size */
2513 0, /* private_flags */
2519 if (!NT_STATUS_IS_OK(status)) {
2520 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2521 nt_errstr(status)));
2525 status = can_set_delete_on_close(fsp, fattr);
2526 if (!NT_STATUS_IS_OK(status)) {
2527 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2529 smb_fname_str_dbg(smb_fname),
2530 nt_errstr(status)));
2531 close_file(req, fsp, NORMAL_CLOSE);
2535 /* The set is across all open files on this dev/inode pair. */
2536 if (!set_delete_on_close(fsp, True, &conn->session_info->utok)) {
2537 close_file(req, fsp, NORMAL_CLOSE);
2538 return NT_STATUS_ACCESS_DENIED;
2541 return close_file(req, fsp, NORMAL_CLOSE);
2544 /****************************************************************************
2545 The guts of the unlink command, split out so it may be called by the NT SMB
2547 ****************************************************************************/
2549 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2550 uint32 dirtype, struct smb_filename *smb_fname,
2553 char *fname_dir = NULL;
2554 char *fname_mask = NULL;
2556 NTSTATUS status = NT_STATUS_OK;
2557 TALLOC_CTX *ctx = talloc_tos();
2559 /* Split up the directory from the filename/mask. */
2560 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2561 &fname_dir, &fname_mask);
2562 if (!NT_STATUS_IS_OK(status)) {
2567 * We should only check the mangled cache
2568 * here if unix_convert failed. This means
2569 * that the path in 'mask' doesn't exist
2570 * on the file system and so we need to look
2571 * for a possible mangle. This patch from
2572 * Tine Smukavec <valentin.smukavec@hermes.si>.
2575 if (!VALID_STAT(smb_fname->st) &&
2576 mangle_is_mangled(fname_mask, conn->params)) {
2577 char *new_mask = NULL;
2578 mangle_lookup_name_from_8_3(ctx, fname_mask,
2579 &new_mask, conn->params);
2581 TALLOC_FREE(fname_mask);
2582 fname_mask = new_mask;
2589 * Only one file needs to be unlinked. Append the mask back
2590 * onto the directory.
2592 TALLOC_FREE(smb_fname->base_name);
2593 if (ISDOT(fname_dir)) {
2594 /* Ensure we use canonical names on open. */
2595 smb_fname->base_name = talloc_asprintf(smb_fname,
2599 smb_fname->base_name = talloc_asprintf(smb_fname,
2604 if (!smb_fname->base_name) {
2605 status = NT_STATUS_NO_MEMORY;
2609 dirtype = FILE_ATTRIBUTE_NORMAL;
2612 status = check_name(conn, smb_fname->base_name);
2613 if (!NT_STATUS_IS_OK(status)) {
2617 status = do_unlink(conn, req, smb_fname, dirtype);
2618 if (!NT_STATUS_IS_OK(status)) {
2624 struct smb_Dir *dir_hnd = NULL;
2626 const char *dname = NULL;
2627 char *talloced = NULL;
2629 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2630 status = NT_STATUS_OBJECT_NAME_INVALID;
2634 if (strequal(fname_mask,"????????.???")) {
2635 TALLOC_FREE(fname_mask);
2636 fname_mask = talloc_strdup(ctx, "*");
2638 status = NT_STATUS_NO_MEMORY;
2643 status = check_name(conn, fname_dir);
2644 if (!NT_STATUS_IS_OK(status)) {
2648 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2650 if (dir_hnd == NULL) {
2651 status = map_nt_error_from_unix(errno);
2655 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2656 the pattern matches against the long name, otherwise the short name
2657 We don't implement this yet XXXX
2660 status = NT_STATUS_NO_SUCH_FILE;
2662 while ((dname = ReadDirName(dir_hnd, &offset,
2663 &smb_fname->st, &talloced))) {
2664 TALLOC_CTX *frame = talloc_stackframe();
2666 if (!is_visible_file(conn, fname_dir, dname,
2667 &smb_fname->st, true)) {
2669 TALLOC_FREE(talloced);
2673 /* Quick check for "." and ".." */
2674 if (ISDOT(dname) || ISDOTDOT(dname)) {
2676 TALLOC_FREE(talloced);
2680 if(!mask_match(dname, fname_mask,
2681 conn->case_sensitive)) {
2683 TALLOC_FREE(talloced);
2687 TALLOC_FREE(smb_fname->base_name);
2688 if (ISDOT(fname_dir)) {
2689 /* Ensure we use canonical names on open. */
2690 smb_fname->base_name =
2691 talloc_asprintf(smb_fname, "%s",
2694 smb_fname->base_name =
2695 talloc_asprintf(smb_fname, "%s/%s",
2699 if (!smb_fname->base_name) {
2700 TALLOC_FREE(dir_hnd);
2701 status = NT_STATUS_NO_MEMORY;
2703 TALLOC_FREE(talloced);
2707 status = check_name(conn, smb_fname->base_name);
2708 if (!NT_STATUS_IS_OK(status)) {
2709 TALLOC_FREE(dir_hnd);
2711 TALLOC_FREE(talloced);
2715 status = do_unlink(conn, req, smb_fname, dirtype);
2716 if (!NT_STATUS_IS_OK(status)) {
2718 TALLOC_FREE(talloced);
2723 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2724 smb_fname->base_name));
2727 TALLOC_FREE(talloced);
2729 TALLOC_FREE(dir_hnd);
2732 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2733 status = map_nt_error_from_unix(errno);
2737 TALLOC_FREE(fname_dir);
2738 TALLOC_FREE(fname_mask);
2742 /****************************************************************************
2744 ****************************************************************************/
2746 void reply_unlink(struct smb_request *req)
2748 connection_struct *conn = req->conn;
2750 struct smb_filename *smb_fname = NULL;
2753 bool path_contains_wcard = False;
2754 TALLOC_CTX *ctx = talloc_tos();
2756 START_PROFILE(SMBunlink);
2759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2763 dirtype = SVAL(req->vwv+0, 0);
2765 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2766 STR_TERMINATE, &status,
2767 &path_contains_wcard);
2768 if (!NT_STATUS_IS_OK(status)) {
2769 reply_nterror(req, status);
2773 status = filename_convert(ctx, conn,
2774 req->flags2 & FLAGS2_DFS_PATHNAMES,
2776 UCF_COND_ALLOW_WCARD_LCOMP,
2777 &path_contains_wcard,
2779 if (!NT_STATUS_IS_OK(status)) {
2780 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2781 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2782 ERRSRV, ERRbadpath);
2785 reply_nterror(req, status);
2789 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2791 status = unlink_internals(conn, req, dirtype, smb_fname,
2792 path_contains_wcard);
2793 if (!NT_STATUS_IS_OK(status)) {
2794 if (open_was_deferred(req->mid)) {
2795 /* We have re-scheduled this call. */
2798 reply_nterror(req, status);
2802 reply_outbuf(req, 0, 0);
2804 TALLOC_FREE(smb_fname);
2805 END_PROFILE(SMBunlink);
2809 /****************************************************************************
2811 ****************************************************************************/
2813 static void fail_readraw(void)
2815 const char *errstr = talloc_asprintf(talloc_tos(),
2816 "FAIL ! reply_readbraw: socket write fail (%s)",
2821 exit_server_cleanly(errstr);
2824 /****************************************************************************
2825 Fake (read/write) sendfile. Returns -1 on read or write fail.
2826 ****************************************************************************/
2828 ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread)
2831 size_t tosend = nread;
2838 bufsize = MIN(nread, 65536);
2840 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2844 while (tosend > 0) {
2848 if (tosend > bufsize) {
2853 ret = read_file(fsp,buf,startpos,cur_read);
2859 /* If we had a short read, fill with zeros. */
2860 if (ret < cur_read) {
2861 memset(buf + ret, '\0', cur_read - ret);
2864 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2866 char addr[INET6_ADDRSTRLEN];
2868 * Try and give an error message saying what
2871 DEBUG(0, ("write_data failed for client %s. "
2873 get_peer_addr(fsp->conn->sconn->sock, addr,
2880 startpos += cur_read;
2884 return (ssize_t)nread;
2887 /****************************************************************************
2888 Deal with the case of sendfile reading less bytes from the file than
2889 requested. Fill with zeros (all we can do).
2890 ****************************************************************************/
2892 void sendfile_short_send(files_struct *fsp,
2897 #define SHORT_SEND_BUFSIZE 1024
2898 if (nread < headersize) {
2899 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2900 "header for file %s (%s). Terminating\n",
2901 fsp_str_dbg(fsp), strerror(errno)));
2902 exit_server_cleanly("sendfile_short_send failed");
2905 nread -= headersize;
2907 if (nread < smb_maxcnt) {
2908 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2910 exit_server_cleanly("sendfile_short_send: "
2914 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2915 "with zeros !\n", fsp_str_dbg(fsp)));
2917 while (nread < smb_maxcnt) {
2919 * We asked for the real file size and told sendfile
2920 * to not go beyond the end of the file. But it can
2921 * happen that in between our fstat call and the
2922 * sendfile call the file was truncated. This is very
2923 * bad because we have already announced the larger
2924 * number of bytes to the client.
2926 * The best we can do now is to send 0-bytes, just as
2927 * a read from a hole in a sparse file would do.
2929 * This should happen rarely enough that I don't care
2930 * about efficiency here :-)
2934 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2935 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2937 char addr[INET6_ADDRSTRLEN];
2939 * Try and give an error message saying what
2942 DEBUG(0, ("write_data failed for client %s. "
2945 fsp->conn->sconn->sock, addr,
2948 exit_server_cleanly("sendfile_short_send: "
2949 "write_data failed");
2957 /****************************************************************************
2958 Return a readbraw error (4 bytes of zero).
2959 ****************************************************************************/
2961 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2967 smbd_lock_socket(sconn);
2968 if (write_data(sconn->sock,header,4) != 4) {
2969 char addr[INET6_ADDRSTRLEN];
2971 * Try and give an error message saying what
2974 DEBUG(0, ("write_data failed for client %s. "
2976 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2981 smbd_unlock_socket(sconn);
2984 /****************************************************************************
2985 Use sendfile in readbraw.
2986 ****************************************************************************/
2988 static void send_file_readbraw(connection_struct *conn,
2989 struct smb_request *req,
2995 struct smbd_server_connection *sconn = req->sconn;
2996 char *outbuf = NULL;
3000 * We can only use sendfile on a non-chained packet
3001 * but we can use on a non-oplocked file. tridge proved this
3002 * on a train in Germany :-). JRA.
3003 * reply_readbraw has already checked the length.
3006 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3007 (fsp->wcp == NULL) &&
3008 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3009 ssize_t sendfile_read = -1;
3011 DATA_BLOB header_blob;
3013 _smb_setlen(header,nread);
3014 header_blob = data_blob_const(header, 4);
3016 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3017 &header_blob, startpos,
3019 if (sendfile_read == -1) {
3020 /* Returning ENOSYS means no data at all was sent.
3021 * Do this as a normal read. */
3022 if (errno == ENOSYS) {
3023 goto normal_readbraw;
3027 * Special hack for broken Linux with no working sendfile. If we
3028 * return EINTR we sent the header but not the rest of the data.
3029 * Fake this up by doing read/write calls.
3031 if (errno == EINTR) {
3032 /* Ensure we don't do this again. */
3033 set_use_sendfile(SNUM(conn), False);
3034 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3036 if (fake_sendfile(fsp, startpos, nread) == -1) {
3037 DEBUG(0,("send_file_readbraw: "
3038 "fake_sendfile failed for "
3042 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3047 DEBUG(0,("send_file_readbraw: sendfile failed for "
3048 "file %s (%s). Terminating\n",
3049 fsp_str_dbg(fsp), strerror(errno)));
3050 exit_server_cleanly("send_file_readbraw sendfile failed");
3051 } else if (sendfile_read == 0) {
3053 * Some sendfile implementations return 0 to indicate
3054 * that there was a short read, but nothing was
3055 * actually written to the socket. In this case,
3056 * fallback to the normal read path so the header gets
3057 * the correct byte count.
3059 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3060 "bytes falling back to the normal read: "
3061 "%s\n", fsp_str_dbg(fsp)));
3062 goto normal_readbraw;
3065 /* Deal with possible short send. */
3066 if (sendfile_read != 4+nread) {
3067 sendfile_short_send(fsp, sendfile_read, 4, nread);
3074 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3076 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3077 (unsigned)(nread+4)));
3078 reply_readbraw_error(sconn);
3083 ret = read_file(fsp,outbuf+4,startpos,nread);
3084 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3093 _smb_setlen(outbuf,ret);
3094 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3095 char addr[INET6_ADDRSTRLEN];
3097 * Try and give an error message saying what
3100 DEBUG(0, ("write_data failed for client %s. "
3102 get_peer_addr(fsp->conn->sconn->sock, addr,
3109 TALLOC_FREE(outbuf);
3112 /****************************************************************************
3113 Reply to a readbraw (core+ protocol).
3114 ****************************************************************************/
3116 void reply_readbraw(struct smb_request *req)
3118 connection_struct *conn = req->conn;
3119 struct smbd_server_connection *sconn = req->sconn;
3120 ssize_t maxcount,mincount;
3124 struct lock_struct lock;
3127 START_PROFILE(SMBreadbraw);
3129 if (srv_is_signing_active(sconn) ||
3130 is_encrypted_packet(req->inbuf)) {
3131 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3132 "raw reads/writes are disallowed.");
3136 reply_readbraw_error(sconn);
3137 END_PROFILE(SMBreadbraw);
3141 if (sconn->smb1.echo_handler.trusted_fde) {
3142 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3143 "'async smb echo handler = yes'\n"));
3144 reply_readbraw_error(sconn);
3145 END_PROFILE(SMBreadbraw);
3150 * Special check if an oplock break has been issued
3151 * and the readraw request croses on the wire, we must
3152 * return a zero length response here.
3155 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3158 * We have to do a check_fsp by hand here, as
3159 * we must always return 4 zero bytes on error,
3163 if (!fsp || !conn || conn != fsp->conn ||
3164 req->vuid != fsp->vuid ||
3165 fsp->is_directory || fsp->fh->fd == -1) {
3167 * fsp could be NULL here so use the value from the packet. JRA.
3169 DEBUG(3,("reply_readbraw: fnum %d not valid "
3171 (int)SVAL(req->vwv+0, 0)));
3172 reply_readbraw_error(sconn);
3173 END_PROFILE(SMBreadbraw);
3177 /* Do a "by hand" version of CHECK_READ. */
3178 if (!(fsp->can_read ||
3179 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3180 (fsp->access_mask & FILE_EXECUTE)))) {
3181 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3182 (int)SVAL(req->vwv+0, 0)));
3183 reply_readbraw_error(sconn);
3184 END_PROFILE(SMBreadbraw);
3188 flush_write_cache(fsp, READRAW_FLUSH);
3190 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3191 if(req->wct == 10) {
3193 * This is a large offset (64 bit) read.
3195 #ifdef LARGE_SMB_OFF_T
3197 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3199 #else /* !LARGE_SMB_OFF_T */
3202 * Ensure we haven't been sent a >32 bit offset.
3205 if(IVAL(req->vwv+8, 0) != 0) {
3206 DEBUG(0,("reply_readbraw: large offset "
3207 "(%x << 32) used and we don't support "
3208 "64 bit offsets.\n",
3209 (unsigned int)IVAL(req->vwv+8, 0) ));
3210 reply_readbraw_error();
3211 END_PROFILE(SMBreadbraw);
3215 #endif /* LARGE_SMB_OFF_T */
3218 DEBUG(0,("reply_readbraw: negative 64 bit "
3219 "readraw offset (%.0f) !\n",
3220 (double)startpos ));
3221 reply_readbraw_error(sconn);
3222 END_PROFILE(SMBreadbraw);
3227 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3228 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3230 /* ensure we don't overrun the packet size */
3231 maxcount = MIN(65535,maxcount);
3233 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3234 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3237 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3238 reply_readbraw_error(sconn);
3239 END_PROFILE(SMBreadbraw);
3243 if (fsp_stat(fsp) == 0) {
3244 size = fsp->fsp_name->st.st_ex_size;
3247 if (startpos >= size) {
3250 nread = MIN(maxcount,(size - startpos));
3253 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3254 if (nread < mincount)
3258 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3259 "min=%lu nread=%lu\n",
3260 fsp->fnum, (double)startpos,
3261 (unsigned long)maxcount,
3262 (unsigned long)mincount,
3263 (unsigned long)nread ) );
3265 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3267 DEBUG(5,("reply_readbraw finished\n"));
3269 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3271 END_PROFILE(SMBreadbraw);
3276 #define DBGC_CLASS DBGC_LOCKING
3278 /****************************************************************************
3279 Reply to a lockread (core+ protocol).
3280 ****************************************************************************/
3282 void reply_lockread(struct smb_request *req)
3284 connection_struct *conn = req->conn;
3291 struct byte_range_lock *br_lck = NULL;
3293 struct smbd_server_connection *sconn = req->sconn;
3295 START_PROFILE(SMBlockread);
3298 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3299 END_PROFILE(SMBlockread);
3303 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3305 if (!check_fsp(conn, req, fsp)) {
3306 END_PROFILE(SMBlockread);
3310 if (!CHECK_READ(fsp,req)) {
3311 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3312 END_PROFILE(SMBlockread);
3316 numtoread = SVAL(req->vwv+1, 0);
3317 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3319 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3321 reply_outbuf(req, 5, numtoread + 3);
3323 data = smb_buf(req->outbuf) + 3;
3326 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3327 * protocol request that predates the read/write lock concept.
3328 * Thus instead of asking for a read lock here we need to ask
3329 * for a write lock. JRA.
3330 * Note that the requested lock size is unaffected by max_recv.
3333 br_lck = do_lock(req->sconn->msg_ctx,
3335 (uint64_t)req->smbpid,
3336 (uint64_t)numtoread,
3340 False, /* Non-blocking lock. */
3344 TALLOC_FREE(br_lck);
3346 if (NT_STATUS_V(status)) {
3347 reply_nterror(req, status);
3348 END_PROFILE(SMBlockread);
3353 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3356 if (numtoread > sconn->smb1.negprot.max_recv) {
3357 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3358 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3359 (unsigned int)numtoread,
3360 (unsigned int)sconn->smb1.negprot.max_recv));
3361 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3363 nread = read_file(fsp,data,startpos,numtoread);
3366 reply_nterror(req, map_nt_error_from_unix(errno));
3367 END_PROFILE(SMBlockread);
3371 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3373 SSVAL(req->outbuf,smb_vwv0,nread);
3374 SSVAL(req->outbuf,smb_vwv5,nread+3);
3375 p = smb_buf(req->outbuf);
3376 SCVAL(p,0,0); /* pad byte. */
3379 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3380 fsp->fnum, (int)numtoread, (int)nread));
3382 END_PROFILE(SMBlockread);
3387 #define DBGC_CLASS DBGC_ALL
3389 /****************************************************************************
3391 ****************************************************************************/
3393 void reply_read(struct smb_request *req)
3395 connection_struct *conn = req->conn;
3402 struct lock_struct lock;
3403 struct smbd_server_connection *sconn = req->sconn;
3405 START_PROFILE(SMBread);
3408 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3409 END_PROFILE(SMBread);
3413 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3415 if (!check_fsp(conn, req, fsp)) {
3416 END_PROFILE(SMBread);
3420 if (!CHECK_READ(fsp,req)) {
3421 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3422 END_PROFILE(SMBread);
3426 numtoread = SVAL(req->vwv+1, 0);
3427 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3429 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3432 * The requested read size cannot be greater than max_recv. JRA.
3434 if (numtoread > sconn->smb1.negprot.max_recv) {
3435 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3436 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3437 (unsigned int)numtoread,
3438 (unsigned int)sconn->smb1.negprot.max_recv));
3439 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3442 reply_outbuf(req, 5, numtoread+3);
3444 data = smb_buf(req->outbuf) + 3;
3446 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3447 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3450 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3451 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3452 END_PROFILE(SMBread);
3457 nread = read_file(fsp,data,startpos,numtoread);
3460 reply_nterror(req, map_nt_error_from_unix(errno));
3464 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3466 SSVAL(req->outbuf,smb_vwv0,nread);
3467 SSVAL(req->outbuf,smb_vwv5,nread+3);
3468 SCVAL(smb_buf(req->outbuf),0,1);
3469 SSVAL(smb_buf(req->outbuf),1,nread);
3471 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3472 fsp->fnum, (int)numtoread, (int)nread ) );
3475 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3477 END_PROFILE(SMBread);
3481 /****************************************************************************
3483 ****************************************************************************/
3485 static int setup_readX_header(struct smb_request *req, char *outbuf,
3491 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3492 data = smb_buf(outbuf);
3494 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3496 SCVAL(outbuf,smb_vwv0,0xFF);
3497 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3498 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3499 SSVAL(outbuf,smb_vwv6,
3501 + 1 /* the wct field */
3502 + 12 * sizeof(uint16_t) /* vwv */
3503 + 2); /* the buflen field */
3504 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3505 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3506 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3507 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3511 /****************************************************************************
3512 Reply to a read and X - possibly using sendfile.
3513 ****************************************************************************/
3515 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3516 files_struct *fsp, SMB_OFF_T startpos,
3520 struct lock_struct lock;
3521 int saved_errno = 0;
3523 if(fsp_stat(fsp) == -1) {
3524 reply_nterror(req, map_nt_error_from_unix(errno));
3528 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3529 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3532 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3533 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3537 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3538 (startpos > fsp->fsp_name->st.st_ex_size)
3539 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3541 * We already know that we would do a short read, so don't
3542 * try the sendfile() path.
3544 goto nosendfile_read;
3548 * We can only use sendfile on a non-chained packet
3549 * but we can use on a non-oplocked file. tridge proved this
3550 * on a train in Germany :-). JRA.
3553 if (!req_is_in_chain(req) &&
3554 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3555 (fsp->wcp == NULL) &&
3556 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3557 uint8 headerbuf[smb_size + 12 * 2];
3561 * Set up the packet header before send. We
3562 * assume here the sendfile will work (get the
3563 * correct amount of data).
3566 header = data_blob_const(headerbuf, sizeof(headerbuf));
3568 construct_reply_common_req(req, (char *)headerbuf);
3569 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3571 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3572 startpos, smb_maxcnt);
3574 /* Returning ENOSYS means no data at all was sent.
3575 Do this as a normal read. */
3576 if (errno == ENOSYS) {
3581 * Special hack for broken Linux with no working sendfile. If we
3582 * return EINTR we sent the header but not the rest of the data.
3583 * Fake this up by doing read/write calls.
3586 if (errno == EINTR) {
3587 /* Ensure we don't do this again. */
3588 set_use_sendfile(SNUM(conn), False);
3589 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3590 nread = fake_sendfile(fsp, startpos,
3593 DEBUG(0,("send_file_readX: "
3594 "fake_sendfile failed for "
3598 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3600 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3601 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3602 /* No outbuf here means successful sendfile. */
3606 DEBUG(0,("send_file_readX: sendfile failed for file "
3607 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3609 exit_server_cleanly("send_file_readX sendfile failed");
3610 } else if (nread == 0) {
3612 * Some sendfile implementations return 0 to indicate
3613 * that there was a short read, but nothing was
3614 * actually written to the socket. In this case,
3615 * fallback to the normal read path so the header gets
3616 * the correct byte count.
3618 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3619 "falling back to the normal read: %s\n",
3624 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3625 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3627 /* Deal with possible short send. */
3628 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3629 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3631 /* No outbuf here means successful sendfile. */
3632 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3633 SMB_PERFCOUNT_END(&req->pcd);
3639 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3640 uint8 headerbuf[smb_size + 2*12];
3642 construct_reply_common_req(req, (char *)headerbuf);
3643 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3645 /* Send out the header. */
3646 if (write_data(req->sconn->sock, (char *)headerbuf,
3647 sizeof(headerbuf)) != sizeof(headerbuf)) {
3649 char addr[INET6_ADDRSTRLEN];
3651 * Try and give an error message saying what
3654 DEBUG(0, ("write_data failed for client %s. "
3656 get_peer_addr(req->sconn->sock, addr,
3660 DEBUG(0,("send_file_readX: write_data failed for file "
3661 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3663 exit_server_cleanly("send_file_readX sendfile failed");
3665 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3667 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3668 "file %s (%s).\n", fsp_str_dbg(fsp),
3670 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3677 reply_outbuf(req, 12, smb_maxcnt);
3679 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3680 saved_errno = errno;
3682 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3685 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3689 setup_readX_header(req, (char *)req->outbuf, nread);
3691 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3692 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3698 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3699 TALLOC_FREE(req->outbuf);
3703 /****************************************************************************
3704 Reply to a read and X.
3705 ****************************************************************************/
3707 void reply_read_and_X(struct smb_request *req)
3709 connection_struct *conn = req->conn;
3713 bool big_readX = False;
3715 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3718 START_PROFILE(SMBreadX);
3720 if ((req->wct != 10) && (req->wct != 12)) {
3721 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3725 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3726 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3727 smb_maxcnt = SVAL(req->vwv+5, 0);
3729 /* If it's an IPC, pass off the pipe handler. */
3731 reply_pipe_read_and_X(req);
3732 END_PROFILE(SMBreadX);
3736 if (!check_fsp(conn, req, fsp)) {
3737 END_PROFILE(SMBreadX);
3741 if (!CHECK_READ(fsp,req)) {
3742 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3743 END_PROFILE(SMBreadX);
3747 if (global_client_caps & CAP_LARGE_READX) {
3748 size_t upper_size = SVAL(req->vwv+7, 0);
3749 smb_maxcnt |= (upper_size<<16);
3750 if (upper_size > 1) {
3751 /* Can't do this on a chained packet. */
3752 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3753 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3754 END_PROFILE(SMBreadX);
3757 /* We currently don't do this on signed or sealed data. */
3758 if (srv_is_signing_active(req->sconn) ||
3759 is_encrypted_packet(req->inbuf)) {
3760 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3761 END_PROFILE(SMBreadX);
3764 /* Is there room in the reply for this data ? */
3765 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3767 NT_STATUS_INVALID_PARAMETER);
3768 END_PROFILE(SMBreadX);
3775 if (req->wct == 12) {
3776 #ifdef LARGE_SMB_OFF_T
3778 * This is a large offset (64 bit) read.
3780 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3782 #else /* !LARGE_SMB_OFF_T */
3785 * Ensure we haven't been sent a >32 bit offset.
3788 if(IVAL(req->vwv+10, 0) != 0) {
3789 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3790 "used and we don't support 64 bit offsets.\n",
3791 (unsigned int)IVAL(req->vwv+10, 0) ));
3792 END_PROFILE(SMBreadX);
3793 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3797 #endif /* LARGE_SMB_OFF_T */
3802 NTSTATUS status = schedule_aio_read_and_X(conn,
3807 if (NT_STATUS_IS_OK(status)) {
3808 /* Read scheduled - we're done. */
3811 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3812 /* Real error - report to client. */
3813 END_PROFILE(SMBreadX);
3814 reply_nterror(req, status);
3817 /* NT_STATUS_RETRY - fall back to sync read. */
3820 smbd_lock_socket(req->sconn);
3821 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3822 smbd_unlock_socket(req->sconn);
3825 END_PROFILE(SMBreadX);
3829 /****************************************************************************
3830 Error replies to writebraw must have smb_wct == 1. Fix this up.
3831 ****************************************************************************/
3833 void error_to_writebrawerr(struct smb_request *req)
3835 uint8 *old_outbuf = req->outbuf;
3837 reply_outbuf(req, 1, 0);
3839 memcpy(req->outbuf, old_outbuf, smb_size);
3840 TALLOC_FREE(old_outbuf);
3843 /****************************************************************************
3844 Read 4 bytes of a smb packet and return the smb length of the packet.
3845 Store the result in the buffer. This version of the function will
3846 never return a session keepalive (length of zero).
3847 Timeout is in milliseconds.
3848 ****************************************************************************/
3850 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3853 uint8_t msgtype = SMBkeepalive;
3855 while (msgtype == SMBkeepalive) {
3858 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3860 if (!NT_STATUS_IS_OK(status)) {
3861 char addr[INET6_ADDRSTRLEN];
3862 /* Try and give an error message
3863 * saying what client failed. */
3864 DEBUG(0, ("read_fd_with_timeout failed for "
3865 "client %s read error = %s.\n",
3866 get_peer_addr(fd,addr,sizeof(addr)),
3867 nt_errstr(status)));
3871 msgtype = CVAL(inbuf, 0);
3874 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3875 (unsigned long)len));
3877 return NT_STATUS_OK;
3880 /****************************************************************************
3881 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3882 ****************************************************************************/
3884 void reply_writebraw(struct smb_request *req)
3886 connection_struct *conn = req->conn;
3889 ssize_t total_written=0;
3890 size_t numtowrite=0;
3896 struct lock_struct lock;
3899 START_PROFILE(SMBwritebraw);
3902 * If we ever reply with an error, it must have the SMB command
3903 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3906 SCVAL(req->inbuf,smb_com,SMBwritec);
3908 if (srv_is_signing_active(req->sconn)) {
3909 END_PROFILE(SMBwritebraw);
3910 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3911 "raw reads/writes are disallowed.");
3914 if (req->wct < 12) {
3915 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3916 error_to_writebrawerr(req);
3917 END_PROFILE(SMBwritebraw);
3921 if (req->sconn->smb1.echo_handler.trusted_fde) {
3922 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3923 "'async smb echo handler = yes'\n"));
3924 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3925 error_to_writebrawerr(req);
3926 END_PROFILE(SMBwritebraw);
3930 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3931 if (!check_fsp(conn, req, fsp)) {
3932 error_to_writebrawerr(req);
3933 END_PROFILE(SMBwritebraw);
3937 if (!CHECK_WRITE(fsp)) {
3938 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3939 error_to_writebrawerr(req);
3940 END_PROFILE(SMBwritebraw);
3944 tcount = IVAL(req->vwv+1, 0);
3945 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3946 write_through = BITSETW(req->vwv+7,0);
3948 /* We have to deal with slightly different formats depending
3949 on whether we are using the core+ or lanman1.0 protocol */
3951 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3952 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3953 data = smb_buf(req->inbuf);
3955 numtowrite = SVAL(req->vwv+10, 0);
3956 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3959 /* Ensure we don't write bytes past the end of this packet. */
3960 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3961 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3962 error_to_writebrawerr(req);
3963 END_PROFILE(SMBwritebraw);
3967 if (!fsp->print_file) {
3968 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3969 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3972 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3973 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3974 error_to_writebrawerr(req);
3975 END_PROFILE(SMBwritebraw);
3981 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3984 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3985 "wrote=%d sync=%d\n",
3986 fsp->fnum, (double)startpos, (int)numtowrite,
3987 (int)nwritten, (int)write_through));
3989 if (nwritten < (ssize_t)numtowrite) {
3990 reply_nterror(req, NT_STATUS_DISK_FULL);
3991 error_to_writebrawerr(req);
3995 total_written = nwritten;
3997 /* Allocate a buffer of 64k + length. */
3998 buf = TALLOC_ARRAY(NULL, char, 65540);
4000 reply_nterror(req, NT_STATUS_NO_MEMORY);
4001 error_to_writebrawerr(req);
4005 /* Return a SMBwritebraw message to the redirector to tell
4006 * it to send more bytes */
4008 memcpy(buf, req->inbuf, smb_size);
4009 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4010 SCVAL(buf,smb_com,SMBwritebraw);
4011 SSVALS(buf,smb_vwv0,0xFFFF);
4013 if (!srv_send_smb(req->sconn,
4015 false, 0, /* no signing */
4016 IS_CONN_ENCRYPTED(conn),
4018 exit_server_cleanly("reply_writebraw: srv_send_smb "
4022 /* Now read the raw data into the buffer and write it */
4023 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4025 if (!NT_STATUS_IS_OK(status)) {
4026 exit_server_cleanly("secondary writebraw failed");
4029 /* Set up outbuf to return the correct size */
4030 reply_outbuf(req, 1, 0);
4032 if (numtowrite != 0) {
4034 if (numtowrite > 0xFFFF) {
4035 DEBUG(0,("reply_writebraw: Oversize secondary write "
4036 "raw requested (%u). Terminating\n",
4037 (unsigned int)numtowrite ));
4038 exit_server_cleanly("secondary writebraw failed");
4041 if (tcount > nwritten+numtowrite) {
4042 DEBUG(3,("reply_writebraw: Client overestimated the "
4044 (int)tcount,(int)nwritten,(int)numtowrite));
4047 status = read_data(req->sconn->sock, buf+4, numtowrite);
4049 if (!NT_STATUS_IS_OK(status)) {
4050 char addr[INET6_ADDRSTRLEN];
4051 /* Try and give an error message
4052 * saying what client failed. */
4053 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4054 "raw read failed (%s) for client %s. "
4055 "Terminating\n", nt_errstr(status),
4056 get_peer_addr(req->sconn->sock, addr,
4058 exit_server_cleanly("secondary writebraw failed");
4061 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4062 if (nwritten == -1) {
4064 reply_nterror(req, map_nt_error_from_unix(errno));
4065 error_to_writebrawerr(req);
4069 if (nwritten < (ssize_t)numtowrite) {
4070 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4071 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4075 total_written += nwritten;
4080 SSVAL(req->outbuf,smb_vwv0,total_written);
4082 status = sync_file(conn, fsp, write_through);
4083 if (!NT_STATUS_IS_OK(status)) {
4084 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4085 fsp_str_dbg(fsp), nt_errstr(status)));
4086 reply_nterror(req, status);
4087 error_to_writebrawerr(req);
4091 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4093 fsp->fnum, (double)startpos, (int)numtowrite,
4094 (int)total_written));
4096 if (!fsp->print_file) {
4097 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4100 /* We won't return a status if write through is not selected - this
4101 * follows what WfWg does */
4102 END_PROFILE(SMBwritebraw);
4104 if (!write_through && total_written==tcount) {
4106 #if RABBIT_PELLET_FIX
4108 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4109 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
4112 if (!send_keepalive(req->sconn->sock)) {
4113 exit_server_cleanly("reply_writebraw: send of "
4114 "keepalive failed");
4117 TALLOC_FREE(req->outbuf);
4122 if (!fsp->print_file) {
4123 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4126 END_PROFILE(SMBwritebraw);
4131 #define DBGC_CLASS DBGC_LOCKING
4133 /****************************************************************************
4134 Reply to a writeunlock (core+).
4135 ****************************************************************************/
4137 void reply_writeunlock(struct smb_request *req)
4139 connection_struct *conn = req->conn;
4140 ssize_t nwritten = -1;
4144 NTSTATUS status = NT_STATUS_OK;
4146 struct lock_struct lock;
4147 int saved_errno = 0;
4149 START_PROFILE(SMBwriteunlock);
4152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4153 END_PROFILE(SMBwriteunlock);
4157 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4159 if (!check_fsp(conn, req, fsp)) {
4160 END_PROFILE(SMBwriteunlock);
4164 if (!CHECK_WRITE(fsp)) {
4165 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4166 END_PROFILE(SMBwriteunlock);
4170 numtowrite = SVAL(req->vwv+1, 0);
4171 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4172 data = (const char *)req->buf + 3;
4174 if (!fsp->print_file && numtowrite > 0) {
4175 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4176 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4179 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4180 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4181 END_PROFILE(SMBwriteunlock);
4186 /* The special X/Open SMB protocol handling of
4187 zero length writes is *NOT* done for
4189 if(numtowrite == 0) {
4192 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4193 saved_errno = errno;
4196 status = sync_file(conn, fsp, False /* write through */);
4197 if (!NT_STATUS_IS_OK(status)) {
4198 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4199 fsp_str_dbg(fsp), nt_errstr(status)));
4200 reply_nterror(req, status);
4205 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4209 if((nwritten < numtowrite) && (numtowrite != 0)) {
4210 reply_nterror(req, NT_STATUS_DISK_FULL);
4214 if (numtowrite && !fsp->print_file) {
4215 status = do_unlock(req->sconn->msg_ctx,
4217 (uint64_t)req->smbpid,
4218 (uint64_t)numtowrite,
4222 if (NT_STATUS_V(status)) {
4223 reply_nterror(req, status);
4228 reply_outbuf(req, 1, 0);
4230 SSVAL(req->outbuf,smb_vwv0,nwritten);
4232 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4233 fsp->fnum, (int)numtowrite, (int)nwritten));
4236 if (numtowrite && !fsp->print_file) {
4237 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4240 END_PROFILE(SMBwriteunlock);
4245 #define DBGC_CLASS DBGC_ALL
4247 /****************************************************************************
4249 ****************************************************************************/
4251 void reply_write(struct smb_request *req)
4253 connection_struct *conn = req->conn;
4255 ssize_t nwritten = -1;
4259 struct lock_struct lock;
4261 int saved_errno = 0;
4263 START_PROFILE(SMBwrite);
4266 END_PROFILE(SMBwrite);
4267 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4271 /* If it's an IPC, pass off the pipe handler. */
4273 reply_pipe_write(req);
4274 END_PROFILE(SMBwrite);
4278 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4280 if (!check_fsp(conn, req, fsp)) {
4281 END_PROFILE(SMBwrite);
4285 if (!CHECK_WRITE(fsp)) {
4286 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4287 END_PROFILE(SMBwrite);
4291 numtowrite = SVAL(req->vwv+1, 0);
4292 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4293 data = (const char *)req->buf + 3;
4295 if (!fsp->print_file) {
4296 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4297 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4300 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4301 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4302 END_PROFILE(SMBwrite);
4308 * X/Open SMB protocol says that if smb_vwv1 is
4309 * zero then the file size should be extended or
4310 * truncated to the size given in smb_vwv[2-3].
4313 if(numtowrite == 0) {
4315 * This is actually an allocate call, and set EOF. JRA.
4317 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4319 reply_nterror(req, NT_STATUS_DISK_FULL);
4322 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4324 reply_nterror(req, NT_STATUS_DISK_FULL);
4327 trigger_write_time_update_immediate(fsp);
4329 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4332 status = sync_file(conn, fsp, False);
4333 if (!NT_STATUS_IS_OK(status)) {
4334 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4335 fsp_str_dbg(fsp), nt_errstr(status)));
4336 reply_nterror(req, status);
4341 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4345 if((nwritten == 0) && (numtowrite != 0)) {
4346 reply_nterror(req, NT_STATUS_DISK_FULL);
4350 reply_outbuf(req, 1, 0);
4352 SSVAL(req->outbuf,smb_vwv0,nwritten);
4354 if (nwritten < (ssize_t)numtowrite) {
4355 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4356 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4359 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4362 if (!fsp->print_file) {
4363 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4366 END_PROFILE(SMBwrite);
4370 /****************************************************************************
4371 Ensure a buffer is a valid writeX for recvfile purposes.
4372 ****************************************************************************/
4374 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4375 (2*14) + /* word count (including bcc) */ \
4378 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4379 const uint8_t *inbuf)
4382 connection_struct *conn = NULL;
4383 unsigned int doff = 0;
4384 size_t len = smb_len_large(inbuf);
4386 if (is_encrypted_packet(inbuf)) {
4387 /* Can't do this on encrypted
4392 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4396 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4397 CVAL(inbuf,smb_wct) != 14) {
4398 DEBUG(10,("is_valid_writeX_buffer: chained or "
4399 "invalid word length.\n"));
4403 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4405 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4409 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4412 if (IS_PRINT(conn)) {
4413 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4416 doff = SVAL(inbuf,smb_vwv11);
4418 numtowrite = SVAL(inbuf,smb_vwv10);
4420 if (len > doff && len - doff > 0xFFFF) {
4421 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4424 if (numtowrite == 0) {
4425 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4429 /* Ensure the sizes match up. */
4430 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4431 /* no pad byte...old smbclient :-( */
4432 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4434 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4438 if (len - doff != numtowrite) {
4439 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4440 "len = %u, doff = %u, numtowrite = %u\n",
4443 (unsigned int)numtowrite ));
4447 DEBUG(10,("is_valid_writeX_buffer: true "
4448 "len = %u, doff = %u, numtowrite = %u\n",
4451 (unsigned int)numtowrite ));
4456 /****************************************************************************
4457 Reply to a write and X.
4458 ****************************************************************************/
4460 void reply_write_and_X(struct smb_request *req)
4462 connection_struct *conn = req->conn;
4464 struct lock_struct lock;
4469 unsigned int smb_doff;
4470 unsigned int smblen;
4473 int saved_errno = 0;
4475 START_PROFILE(SMBwriteX);
4477 if ((req->wct != 12) && (req->wct != 14)) {
4478 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4479 END_PROFILE(SMBwriteX);
4483 numtowrite = SVAL(req->vwv+10, 0);
4484 smb_doff = SVAL(req->vwv+11, 0);
4485 smblen = smb_len(req->inbuf);
4487 if (req->unread_bytes > 0xFFFF ||
4488 (smblen > smb_doff &&
4489 smblen - smb_doff > 0xFFFF)) {
4490 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4493 if (req->unread_bytes) {
4494 /* Can't do a recvfile write on IPC$ */
4496 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4497 END_PROFILE(SMBwriteX);
4500 if (numtowrite != req->unread_bytes) {
4501 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4502 END_PROFILE(SMBwriteX);
4506 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4507 smb_doff + numtowrite > smblen) {
4508 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4509 END_PROFILE(SMBwriteX);
4514 /* If it's an IPC, pass off the pipe handler. */
4516 if (req->unread_bytes) {
4517 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4518 END_PROFILE(SMBwriteX);
4521 reply_pipe_write_and_X(req);
4522 END_PROFILE(SMBwriteX);
4526 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4527 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4528 write_through = BITSETW(req->vwv+7,0);
4530 if (!check_fsp(conn, req, fsp)) {
4531 END_PROFILE(SMBwriteX);
4535 if (!CHECK_WRITE(fsp)) {
4536 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4537 END_PROFILE(SMBwriteX);
4541 data = smb_base(req->inbuf) + smb_doff;
4543 if(req->wct == 14) {
4544 #ifdef LARGE_SMB_OFF_T
4546 * This is a large offset (64 bit) write.
4548 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4550 #else /* !LARGE_SMB_OFF_T */
4553 * Ensure we haven't been sent a >32 bit offset.
4556 if(IVAL(req->vwv+12, 0) != 0) {
4557 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4558 "used and we don't support 64 bit offsets.\n",
4559 (unsigned int)IVAL(req->vwv+12, 0) ));
4560 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4561 END_PROFILE(SMBwriteX);
4565 #endif /* LARGE_SMB_OFF_T */
4568 /* X/Open SMB protocol says that, unlike SMBwrite
4569 if the length is zero then NO truncation is
4570 done, just a write of zero. To truncate a file,
4573 if(numtowrite == 0) {
4576 if (req->unread_bytes == 0) {
4577 status = schedule_aio_write_and_X(conn,
4584 if (NT_STATUS_IS_OK(status)) {
4585 /* write scheduled - we're done. */
4588 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4589 /* Real error - report to client. */
4590 reply_nterror(req, status);
4593 /* NT_STATUS_RETRY - fall through to sync write. */
4596 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4597 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4600 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4601 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4605 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4606 saved_errno = errno;
4608 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4612 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4616 if((nwritten == 0) && (numtowrite != 0)) {
4617 reply_nterror(req, NT_STATUS_DISK_FULL);
4621 reply_outbuf(req, 6, 0);
4622 SSVAL(req->outbuf,smb_vwv2,nwritten);
4623 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4625 if (nwritten < (ssize_t)numtowrite) {
4626 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4627 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4630 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4631 fsp->fnum, (int)numtowrite, (int)nwritten));
4633 status = sync_file(conn, fsp, write_through);
4634 if (!NT_STATUS_IS_OK(status)) {
4635 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4636 fsp_str_dbg(fsp), nt_errstr(status)));
4637 reply_nterror(req, status);
4641 END_PROFILE(SMBwriteX);
4646 END_PROFILE(SMBwriteX);
4650 /****************************************************************************
4652 ****************************************************************************/
4654 void reply_lseek(struct smb_request *req)
4656 connection_struct *conn = req->conn;
4662 START_PROFILE(SMBlseek);
4665 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4666 END_PROFILE(SMBlseek);
4670 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4672 if (!check_fsp(conn, req, fsp)) {
4676 flush_write_cache(fsp, SEEK_FLUSH);
4678 mode = SVAL(req->vwv+1, 0) & 3;
4679 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4680 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4689 res = fsp->fh->pos + startpos;
4700 if (umode == SEEK_END) {
4701 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4702 if(errno == EINVAL) {
4703 SMB_OFF_T current_pos = startpos;
4705 if(fsp_stat(fsp) == -1) {
4707 map_nt_error_from_unix(errno));
4708 END_PROFILE(SMBlseek);
4712 current_pos += fsp->fsp_name->st.st_ex_size;
4714 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4719 reply_nterror(req, map_nt_error_from_unix(errno));
4720 END_PROFILE(SMBlseek);
4727 reply_outbuf(req, 2, 0);
4728 SIVAL(req->outbuf,smb_vwv0,res);
4730 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4731 fsp->fnum, (double)startpos, (double)res, mode));
4733 END_PROFILE(SMBlseek);
4737 /****************************************************************************
4739 ****************************************************************************/
4741 void reply_flush(struct smb_request *req)
4743 connection_struct *conn = req->conn;
4747 START_PROFILE(SMBflush);
4750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4754 fnum = SVAL(req->vwv+0, 0);
4755 fsp = file_fsp(req, fnum);
4757 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4762 file_sync_all(conn);
4764 NTSTATUS status = sync_file(conn, fsp, True);
4765 if (!NT_STATUS_IS_OK(status)) {
4766 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4767 fsp_str_dbg(fsp), nt_errstr(status)));
4768 reply_nterror(req, status);
4769 END_PROFILE(SMBflush);
4774 reply_outbuf(req, 0, 0);
4776 DEBUG(3,("flush\n"));
4777 END_PROFILE(SMBflush);
4781 /****************************************************************************
4783 conn POINTER CAN BE NULL HERE !
4784 ****************************************************************************/
4786 void reply_exit(struct smb_request *req)
4788 START_PROFILE(SMBexit);
4790 file_close_pid(req->sconn, req->smbpid, req->vuid);
4792 reply_outbuf(req, 0, 0);
4794 DEBUG(3,("exit\n"));
4796 END_PROFILE(SMBexit);
4800 /****************************************************************************
4801 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4802 ****************************************************************************/
4804 void reply_close(struct smb_request *req)
4806 connection_struct *conn = req->conn;
4807 NTSTATUS status = NT_STATUS_OK;
4808 files_struct *fsp = NULL;
4809 START_PROFILE(SMBclose);
4812 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4813 END_PROFILE(SMBclose);
4817 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4820 * We can only use check_fsp if we know it's not a directory.
4823 if (!check_fsp_open(conn, req, fsp)) {
4824 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4825 END_PROFILE(SMBclose);
4829 if(fsp->is_directory) {
4831 * Special case - close NT SMB directory handle.
4833 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4834 status = close_file(req, fsp, NORMAL_CLOSE);
4838 * Close ordinary file.
4841 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4842 fsp->fh->fd, fsp->fnum,
4843 conn->num_files_open));
4846 * Take care of any time sent in the close.
4849 t = srv_make_unix_date3(req->vwv+1);
4850 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4853 * close_file() returns the unix errno if an error
4854 * was detected on close - normally this is due to
4855 * a disk full error. If not then it was probably an I/O error.
4858 status = close_file(req, fsp, NORMAL_CLOSE);
4861 if (!NT_STATUS_IS_OK(status)) {
4862 reply_nterror(req, status);
4863 END_PROFILE(SMBclose);
4867 reply_outbuf(req, 0, 0);
4868 END_PROFILE(SMBclose);
4872 /****************************************************************************
4873 Reply to a writeclose (Core+ protocol).
4874 ****************************************************************************/
4876 void reply_writeclose(struct smb_request *req)
4878 connection_struct *conn = req->conn;
4880 ssize_t nwritten = -1;
4881 NTSTATUS close_status = NT_STATUS_OK;
4884 struct timespec mtime;
4886 struct lock_struct lock;
4888 START_PROFILE(SMBwriteclose);
4891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4892 END_PROFILE(SMBwriteclose);
4896 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4898 if (!check_fsp(conn, req, fsp)) {
4899 END_PROFILE(SMBwriteclose);
4902 if (!CHECK_WRITE(fsp)) {
4903 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4904 END_PROFILE(SMBwriteclose);
4908 numtowrite = SVAL(req->vwv+1, 0);
4909 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4910 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4911 data = (const char *)req->buf + 1;
4913 if (!fsp->print_file) {
4914 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4915 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4918 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4919 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4920 END_PROFILE(SMBwriteclose);
4925 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4927 set_close_write_time(fsp, mtime);
4930 * More insanity. W2K only closes the file if writelen > 0.
4935 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4936 "file %s\n", fsp_str_dbg(fsp)));
4937 close_status = close_file(req, fsp, NORMAL_CLOSE);
4940 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4941 fsp->fnum, (int)numtowrite, (int)nwritten,
4942 conn->num_files_open));
4944 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4945 reply_nterror(req, NT_STATUS_DISK_FULL);
4949 if(!NT_STATUS_IS_OK(close_status)) {
4950 reply_nterror(req, close_status);
4954 reply_outbuf(req, 1, 0);
4956 SSVAL(req->outbuf,smb_vwv0,nwritten);
4959 if (numtowrite && !fsp->print_file) {
4960 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4963 END_PROFILE(SMBwriteclose);
4968 #define DBGC_CLASS DBGC_LOCKING
4970 /****************************************************************************
4972 ****************************************************************************/
4974 void reply_lock(struct smb_request *req)
4976 connection_struct *conn = req->conn;
4977 uint64_t count,offset;
4980 struct byte_range_lock *br_lck = NULL;
4982 START_PROFILE(SMBlock);
4985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4986 END_PROFILE(SMBlock);
4990 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4992 if (!check_fsp(conn, req, fsp)) {
4993 END_PROFILE(SMBlock);
4997 count = (uint64_t)IVAL(req->vwv+1, 0);
4998 offset = (uint64_t)IVAL(req->vwv+3, 0);
5000 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5001 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
5003 br_lck = do_lock(req->sconn->msg_ctx,
5005 (uint64_t)req->smbpid,
5010 False, /* Non-blocking lock. */
5015 TALLOC_FREE(br_lck);
5017 if (NT_STATUS_V(status)) {
5018 reply_nterror(req, status);
5019 END_PROFILE(SMBlock);
5023 reply_outbuf(req, 0, 0);
5025 END_PROFILE(SMBlock);
5029 /****************************************************************************
5031 ****************************************************************************/
5033 void reply_unlock(struct smb_request *req)
5035 connection_struct *conn = req->conn;
5036 uint64_t count,offset;
5040 START_PROFILE(SMBunlock);
5043 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5044 END_PROFILE(SMBunlock);
5048 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5050 if (!check_fsp(conn, req, fsp)) {
5051 END_PROFILE(SMBunlock);
5055 count = (uint64_t)IVAL(req->vwv+1, 0);
5056 offset = (uint64_t)IVAL(req->vwv+3, 0);
5058 status = do_unlock(req->sconn->msg_ctx,
5060 (uint64_t)req->smbpid,
5065 if (NT_STATUS_V(status)) {
5066 reply_nterror(req, status);
5067 END_PROFILE(SMBunlock);
5071 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5072 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5074 reply_outbuf(req, 0, 0);
5076 END_PROFILE(SMBunlock);
5081 #define DBGC_CLASS DBGC_ALL
5083 /****************************************************************************
5085 conn POINTER CAN BE NULL HERE !
5086 ****************************************************************************/
5088 void reply_tdis(struct smb_request *req)
5090 connection_struct *conn = req->conn;
5091 START_PROFILE(SMBtdis);
5094 DEBUG(4,("Invalid connection in tdis\n"));
5095 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5096 END_PROFILE(SMBtdis);
5102 close_cnum(conn,req->vuid);
5105 reply_outbuf(req, 0, 0);
5106 END_PROFILE(SMBtdis);
5110 /****************************************************************************
5112 conn POINTER CAN BE NULL HERE !
5113 ****************************************************************************/
5115 void reply_echo(struct smb_request *req)
5117 connection_struct *conn = req->conn;
5118 struct smb_perfcount_data local_pcd;
5119 struct smb_perfcount_data *cur_pcd;
5123 START_PROFILE(SMBecho);
5125 smb_init_perfcount_data(&local_pcd);
5128 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5129 END_PROFILE(SMBecho);
5133 smb_reverb = SVAL(req->vwv+0, 0);
5135 reply_outbuf(req, 1, req->buflen);
5137 /* copy any incoming data back out */
5138 if (req->buflen > 0) {
5139 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5142 if (smb_reverb > 100) {
5143 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5147 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5149 /* this makes sure we catch the request pcd */
5150 if (seq_num == smb_reverb) {
5151 cur_pcd = &req->pcd;
5153 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5154 cur_pcd = &local_pcd;
5157 SSVAL(req->outbuf,smb_vwv0,seq_num);
5159 show_msg((char *)req->outbuf);
5160 if (!srv_send_smb(req->sconn,
5161 (char *)req->outbuf,
5162 true, req->seqnum+1,
5163 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5165 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5168 DEBUG(3,("echo %d times\n", smb_reverb));
5170 TALLOC_FREE(req->outbuf);
5172 END_PROFILE(SMBecho);
5176 /****************************************************************************
5177 Reply to a printopen.
5178 ****************************************************************************/
5180 void reply_printopen(struct smb_request *req)
5182 connection_struct *conn = req->conn;
5186 START_PROFILE(SMBsplopen);
5189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5190 END_PROFILE(SMBsplopen);
5194 if (!CAN_PRINT(conn)) {
5195 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5196 END_PROFILE(SMBsplopen);
5200 status = file_new(req, conn, &fsp);
5201 if(!NT_STATUS_IS_OK(status)) {
5202 reply_nterror(req, status);
5203 END_PROFILE(SMBsplopen);
5207 /* Open for exclusive use, write only. */
5208 status = print_spool_open(fsp, NULL, req->vuid);
5210 if (!NT_STATUS_IS_OK(status)) {
5211 file_free(req, fsp);
5212 reply_nterror(req, status);
5213 END_PROFILE(SMBsplopen);
5217 reply_outbuf(req, 1, 0);
5218 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5220 DEBUG(3,("openprint fd=%d fnum=%d\n",
5221 fsp->fh->fd, fsp->fnum));
5223 END_PROFILE(SMBsplopen);
5227 /****************************************************************************
5228 Reply to a printclose.
5229 ****************************************************************************/
5231 void reply_printclose(struct smb_request *req)
5233 connection_struct *conn = req->conn;
5237 START_PROFILE(SMBsplclose);
5240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5241 END_PROFILE(SMBsplclose);
5245 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5247 if (!check_fsp(conn, req, fsp)) {
5248 END_PROFILE(SMBsplclose);
5252 if (!CAN_PRINT(conn)) {
5253 reply_force_doserror(req, ERRSRV, ERRerror);
5254 END_PROFILE(SMBsplclose);
5258 DEBUG(3,("printclose fd=%d fnum=%d\n",
5259 fsp->fh->fd,fsp->fnum));
5261 status = close_file(req, fsp, NORMAL_CLOSE);
5263 if(!NT_STATUS_IS_OK(status)) {
5264 reply_nterror(req, status);
5265 END_PROFILE(SMBsplclose);
5269 reply_outbuf(req, 0, 0);
5271 END_PROFILE(SMBsplclose);
5275 /****************************************************************************
5276 Reply to a printqueue.
5277 ****************************************************************************/
5279 void reply_printqueue(struct smb_request *req)
5281 connection_struct *conn = req->conn;
5285 START_PROFILE(SMBsplretq);
5288 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5289 END_PROFILE(SMBsplretq);
5293 max_count = SVAL(req->vwv+0, 0);
5294 start_index = SVAL(req->vwv+1, 0);
5296 /* we used to allow the client to get the cnum wrong, but that
5297 is really quite gross and only worked when there was only
5298 one printer - I think we should now only accept it if they
5299 get it right (tridge) */
5300 if (!CAN_PRINT(conn)) {
5301 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5302 END_PROFILE(SMBsplretq);
5306 reply_outbuf(req, 2, 3);
5307 SSVAL(req->outbuf,smb_vwv0,0);
5308 SSVAL(req->outbuf,smb_vwv1,0);
5309 SCVAL(smb_buf(req->outbuf),0,1);
5310 SSVAL(smb_buf(req->outbuf),1,0);
5312 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5313 start_index, max_count));
5316 TALLOC_CTX *mem_ctx = talloc_tos();
5319 const char *sharename = lp_servicename(SNUM(conn));
5320 struct rpc_pipe_client *cli = NULL;
5321 struct dcerpc_binding_handle *b = NULL;
5322 struct policy_handle handle;
5323 struct spoolss_DevmodeContainer devmode_ctr;
5324 union spoolss_JobInfo *info;
5326 uint32_t num_to_get;
5330 ZERO_STRUCT(handle);
5332 status = rpc_pipe_open_interface(conn,
5333 &ndr_table_spoolss.syntax_id,
5335 &conn->sconn->client_id,
5336 conn->sconn->msg_ctx,
5338 if (!NT_STATUS_IS_OK(status)) {
5339 DEBUG(0, ("reply_printqueue: "
5340 "could not connect to spoolss: %s\n",
5341 nt_errstr(status)));
5342 reply_nterror(req, status);
5345 b = cli->binding_handle;
5347 ZERO_STRUCT(devmode_ctr);
5349 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5352 SEC_FLAG_MAXIMUM_ALLOWED,
5355 if (!NT_STATUS_IS_OK(status)) {
5356 reply_nterror(req, status);
5359 if (!W_ERROR_IS_OK(werr)) {
5360 reply_nterror(req, werror_to_ntstatus(werr));
5364 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5372 if (!W_ERROR_IS_OK(werr)) {
5373 reply_nterror(req, werror_to_ntstatus(werr));
5377 if (max_count > 0) {
5378 first = start_index;
5380 first = start_index + max_count + 1;
5383 if (first >= count) {
5386 num_to_get = first + MIN(ABS(max_count), count - first);
5389 for (i = first; i < num_to_get; i++) {
5392 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5394 uint16_t qrapjobid = pjobid_to_rap(sharename,
5395 info[i].info2.job_id);
5397 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5403 srv_put_dos_date2(p, 0, qtime);
5404 SCVAL(p, 4, qstatus);
5405 SSVAL(p, 5, qrapjobid);
5406 SIVAL(p, 7, info[i].info2.size);
5408 srvstr_push(blob, req->flags2, p+12,
5409 info[i].info2.notify_name, 16, STR_ASCII);
5411 if (message_push_blob(
5414 blob, sizeof(blob))) == -1) {
5415 reply_nterror(req, NT_STATUS_NO_MEMORY);
5421 SSVAL(req->outbuf,smb_vwv0,count);
5422 SSVAL(req->outbuf,smb_vwv1,
5423 (max_count>0?first+count:first-1));
5424 SCVAL(smb_buf(req->outbuf),0,1);
5425 SSVAL(smb_buf(req->outbuf),1,28*count);
5429 DEBUG(3, ("%u entries returned in queue\n",
5433 if (b && is_valid_policy_hnd(&handle)) {
5434 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5439 END_PROFILE(SMBsplretq);
5443 /****************************************************************************
5444 Reply to a printwrite.
5445 ****************************************************************************/
5447 void reply_printwrite(struct smb_request *req)
5449 connection_struct *conn = req->conn;
5454 START_PROFILE(SMBsplwr);
5457 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5458 END_PROFILE(SMBsplwr);
5462 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5464 if (!check_fsp(conn, req, fsp)) {
5465 END_PROFILE(SMBsplwr);
5469 if (!fsp->print_file) {
5470 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5471 END_PROFILE(SMBsplwr);
5475 if (!CHECK_WRITE(fsp)) {
5476 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5477 END_PROFILE(SMBsplwr);
5481 numtowrite = SVAL(req->buf, 1);
5483 if (req->buflen < numtowrite + 3) {
5484 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5485 END_PROFILE(SMBsplwr);
5489 data = (const char *)req->buf + 3;
5491 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5492 reply_nterror(req, map_nt_error_from_unix(errno));
5493 END_PROFILE(SMBsplwr);
5497 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5499 END_PROFILE(SMBsplwr);
5503 /****************************************************************************
5505 ****************************************************************************/
5507 void reply_mkdir(struct smb_request *req)
5509 connection_struct *conn = req->conn;
5510 struct smb_filename *smb_dname = NULL;
5511 char *directory = NULL;
5513 TALLOC_CTX *ctx = talloc_tos();
5515 START_PROFILE(SMBmkdir);
5517 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5518 STR_TERMINATE, &status);
5519 if (!NT_STATUS_IS_OK(status)) {
5520 reply_nterror(req, status);
5524 status = filename_convert(ctx, conn,
5525 req->flags2 & FLAGS2_DFS_PATHNAMES,
5530 if (!NT_STATUS_IS_OK(status)) {
5531 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5532 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5533 ERRSRV, ERRbadpath);
5536 reply_nterror(req, status);
5540 status = create_directory(conn, req, smb_dname);
5542 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5544 if (!NT_STATUS_IS_OK(status)) {
5546 if (!use_nt_status()
5547 && NT_STATUS_EQUAL(status,
5548 NT_STATUS_OBJECT_NAME_COLLISION)) {
5550 * Yes, in the DOS error code case we get a
5551 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5552 * samba4 torture test.
5554 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5557 reply_nterror(req, status);
5561 reply_outbuf(req, 0, 0);
5563 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5565 TALLOC_FREE(smb_dname);
5566 END_PROFILE(SMBmkdir);
5570 /****************************************************************************
5572 ****************************************************************************/
5574 void reply_rmdir(struct smb_request *req)
5576 connection_struct *conn = req->conn;
5577 struct smb_filename *smb_dname = NULL;
5578 char *directory = NULL;
5580 TALLOC_CTX *ctx = talloc_tos();
5581 files_struct *fsp = NULL;
5583 struct smbd_server_connection *sconn = req->sconn;
5585 START_PROFILE(SMBrmdir);
5587 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5588 STR_TERMINATE, &status);
5589 if (!NT_STATUS_IS_OK(status)) {
5590 reply_nterror(req, status);
5594 status = filename_convert(ctx, conn,
5595 req->flags2 & FLAGS2_DFS_PATHNAMES,
5600 if (!NT_STATUS_IS_OK(status)) {
5601 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5602 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5603 ERRSRV, ERRbadpath);
5606 reply_nterror(req, status);
5610 if (is_ntfs_stream_smb_fname(smb_dname)) {
5611 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5615 status = SMB_VFS_CREATE_FILE(
5618 0, /* root_dir_fid */
5619 smb_dname, /* fname */
5620 DELETE_ACCESS, /* access_mask */
5621 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5623 FILE_OPEN, /* create_disposition*/
5624 FILE_DIRECTORY_FILE, /* create_options */
5625 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5626 0, /* oplock_request */
5627 0, /* allocation_size */
5628 0, /* private_flags */
5634 if (!NT_STATUS_IS_OK(status)) {
5635 if (open_was_deferred(req->mid)) {
5636 /* We have re-scheduled this call. */
5639 reply_nterror(req, status);
5643 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5644 if (!NT_STATUS_IS_OK(status)) {
5645 close_file(req, fsp, ERROR_CLOSE);
5646 reply_nterror(req, status);
5650 if (!set_delete_on_close(fsp, true, &conn->session_info->utok)) {
5651 close_file(req, fsp, ERROR_CLOSE);
5652 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5656 status = close_file(req, fsp, NORMAL_CLOSE);
5657 if (!NT_STATUS_IS_OK(status)) {
5658 reply_nterror(req, status);
5660 reply_outbuf(req, 0, 0);
5663 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5665 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5667 TALLOC_FREE(smb_dname);
5668 END_PROFILE(SMBrmdir);
5672 /*******************************************************************
5673 Resolve wildcards in a filename rename.
5674 ********************************************************************/
5676 static bool resolve_wildcards(TALLOC_CTX *ctx,
5681 char *name2_copy = NULL;
5686 char *p,*p2, *pname1, *pname2;
5688 name2_copy = talloc_strdup(ctx, name2);
5693 pname1 = strrchr_m(name1,'/');
5694 pname2 = strrchr_m(name2_copy,'/');
5696 if (!pname1 || !pname2) {
5700 /* Truncate the copy of name2 at the last '/' */
5703 /* Now go past the '/' */
5707 root1 = talloc_strdup(ctx, pname1);
5708 root2 = talloc_strdup(ctx, pname2);
5710 if (!root1 || !root2) {
5714 p = strrchr_m(root1,'.');
5717 ext1 = talloc_strdup(ctx, p+1);
5719 ext1 = talloc_strdup(ctx, "");
5721 p = strrchr_m(root2,'.');
5724 ext2 = talloc_strdup(ctx, p+1);
5726 ext2 = talloc_strdup(ctx, "");
5729 if (!ext1 || !ext2) {
5737 /* Hmmm. Should this be mb-aware ? */
5740 } else if (*p2 == '*') {
5742 root2 = talloc_asprintf(ctx, "%s%s",
5761 /* Hmmm. Should this be mb-aware ? */
5764 } else if (*p2 == '*') {
5766 ext2 = talloc_asprintf(ctx, "%s%s",
5782 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5787 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5799 /****************************************************************************
5800 Ensure open files have their names updated. Updated to notify other smbd's
5802 ****************************************************************************/
5804 static void rename_open_files(connection_struct *conn,
5805 struct share_mode_lock *lck,
5806 uint32_t orig_name_hash,
5807 const struct smb_filename *smb_fname_dst)
5810 bool did_rename = False;
5812 uint32_t new_name_hash;
5814 for(fsp = file_find_di_first(conn->sconn, lck->id); fsp;
5815 fsp = file_find_di_next(fsp)) {
5816 /* fsp_name is a relative path under the fsp. To change this for other
5817 sharepaths we need to manipulate relative paths. */
5818 /* TODO - create the absolute path and manipulate the newname
5819 relative to the sharepath. */
5820 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5823 if (fsp->name_hash != orig_name_hash) {
5826 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5827 "(file_id %s) from %s -> %s\n", fsp->fnum,
5828 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5829 smb_fname_str_dbg(smb_fname_dst)));
5831 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5832 if (NT_STATUS_IS_OK(status)) {
5834 new_name_hash = fsp->name_hash;
5839 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5840 "for %s\n", file_id_string_tos(&lck->id),
5841 smb_fname_str_dbg(smb_fname_dst)));
5844 /* Send messages to all smbd's (not ourself) that the name has changed. */
5845 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5846 orig_name_hash, new_name_hash,
5851 /****************************************************************************
5852 We need to check if the source path is a parent directory of the destination
5853 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5854 refuse the rename with a sharing violation. Under UNIX the above call can
5855 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5856 probably need to check that the client is a Windows one before disallowing
5857 this as a UNIX client (one with UNIX extensions) can know the source is a
5858 symlink and make this decision intelligently. Found by an excellent bug
5859 report from <AndyLiebman@aol.com>.
5860 ****************************************************************************/
5862 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5863 const struct smb_filename *smb_fname_dst)
5865 const char *psrc = smb_fname_src->base_name;
5866 const char *pdst = smb_fname_dst->base_name;
5869 if (psrc[0] == '.' && psrc[1] == '/') {
5872 if (pdst[0] == '.' && pdst[1] == '/') {
5875 if ((slen = strlen(psrc)) > strlen(pdst)) {
5878 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5882 * Do the notify calls from a rename
5885 static void notify_rename(connection_struct *conn, bool is_dir,
5886 const struct smb_filename *smb_fname_src,
5887 const struct smb_filename *smb_fname_dst)
5889 char *parent_dir_src = NULL;
5890 char *parent_dir_dst = NULL;
5893 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5894 : FILE_NOTIFY_CHANGE_FILE_NAME;
5896 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5897 &parent_dir_src, NULL) ||
5898 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5899 &parent_dir_dst, NULL)) {
5903 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5904 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5905 smb_fname_src->base_name);
5906 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5907 smb_fname_dst->base_name);
5910 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5911 smb_fname_src->base_name);
5912 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5913 smb_fname_dst->base_name);
5916 /* this is a strange one. w2k3 gives an additional event for
5917 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5918 files, but not directories */
5920 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5921 FILE_NOTIFY_CHANGE_ATTRIBUTES
5922 |FILE_NOTIFY_CHANGE_CREATION,
5923 smb_fname_dst->base_name);
5926 TALLOC_FREE(parent_dir_src);
5927 TALLOC_FREE(parent_dir_dst);
5930 /****************************************************************************
5931 Rename an open file - given an fsp.
5932 ****************************************************************************/
5934 NTSTATUS rename_internals_fsp(connection_struct *conn,
5936 const struct smb_filename *smb_fname_dst_in,
5938 bool replace_if_exists)
5940 TALLOC_CTX *ctx = talloc_tos();
5941 struct smb_filename *smb_fname_dst = NULL;
5942 NTSTATUS status = NT_STATUS_OK;
5943 struct share_mode_lock *lck = NULL;
5944 bool dst_exists, old_is_stream, new_is_stream;
5946 status = check_name(conn, smb_fname_dst_in->base_name);
5947 if (!NT_STATUS_IS_OK(status)) {
5951 /* Make a copy of the dst smb_fname structs */
5953 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5954 if (!NT_STATUS_IS_OK(status)) {
5959 * Check for special case with case preserving and not
5960 * case sensitive. If the old last component differs from the original
5961 * last component only by case, then we should allow
5962 * the rename (user is trying to change the case of the
5965 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5966 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5967 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5969 char *fname_dst_lcomp_base_mod = NULL;
5970 struct smb_filename *smb_fname_orig_lcomp = NULL;
5973 * Get the last component of the destination name.
5975 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5977 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5979 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
5981 if (!fname_dst_lcomp_base_mod) {
5982 status = NT_STATUS_NO_MEMORY;
5987 * Create an smb_filename struct using the original last
5988 * component of the destination.
5990 status = create_synthetic_smb_fname_split(ctx,
5991 smb_fname_dst->original_lcomp, NULL,
5992 &smb_fname_orig_lcomp);
5993 if (!NT_STATUS_IS_OK(status)) {
5994 TALLOC_FREE(fname_dst_lcomp_base_mod);
5998 /* If the base names only differ by case, use original. */
5999 if(!strcsequal(fname_dst_lcomp_base_mod,
6000 smb_fname_orig_lcomp->base_name)) {
6003 * Replace the modified last component with the
6007 *last_slash = '\0'; /* Truncate at the '/' */
6008 tmp = talloc_asprintf(smb_fname_dst,
6010 smb_fname_dst->base_name,
6011 smb_fname_orig_lcomp->base_name);
6013 tmp = talloc_asprintf(smb_fname_dst,
6015 smb_fname_orig_lcomp->base_name);
6018 status = NT_STATUS_NO_MEMORY;
6019 TALLOC_FREE(fname_dst_lcomp_base_mod);
6020 TALLOC_FREE(smb_fname_orig_lcomp);
6023 TALLOC_FREE(smb_fname_dst->base_name);
6024 smb_fname_dst->base_name = tmp;
6027 /* If the stream_names only differ by case, use original. */
6028 if(!strcsequal(smb_fname_dst->stream_name,
6029 smb_fname_orig_lcomp->stream_name)) {
6031 /* Use the original stream. */
6032 tmp = talloc_strdup(smb_fname_dst,
6033 smb_fname_orig_lcomp->stream_name);
6035 status = NT_STATUS_NO_MEMORY;
6036 TALLOC_FREE(fname_dst_lcomp_base_mod);
6037 TALLOC_FREE(smb_fname_orig_lcomp);
6040 TALLOC_FREE(smb_fname_dst->stream_name);
6041 smb_fname_dst->stream_name = tmp;
6043 TALLOC_FREE(fname_dst_lcomp_base_mod);
6044 TALLOC_FREE(smb_fname_orig_lcomp);
6048 * If the src and dest names are identical - including case,
6049 * don't do the rename, just return success.
6052 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6053 strcsequal(fsp->fsp_name->stream_name,
6054 smb_fname_dst->stream_name)) {
6055 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6056 "- returning success\n",
6057 smb_fname_str_dbg(smb_fname_dst)));
6058 status = NT_STATUS_OK;
6062 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6063 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6065 /* Return the correct error code if both names aren't streams. */
6066 if (!old_is_stream && new_is_stream) {
6067 status = NT_STATUS_OBJECT_NAME_INVALID;
6071 if (old_is_stream && !new_is_stream) {
6072 status = NT_STATUS_INVALID_PARAMETER;
6076 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6078 if(!replace_if_exists && dst_exists) {
6079 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6080 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6081 smb_fname_str_dbg(smb_fname_dst)));
6082 status = NT_STATUS_OBJECT_NAME_COLLISION;
6087 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6088 &smb_fname_dst->st);
6089 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6091 /* The file can be open when renaming a stream */
6092 if (dst_fsp && !new_is_stream) {
6093 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6094 status = NT_STATUS_ACCESS_DENIED;
6099 /* Ensure we have a valid stat struct for the source. */
6100 status = vfs_stat_fsp(fsp);
6101 if (!NT_STATUS_IS_OK(status)) {
6105 status = can_rename(conn, fsp, attrs);
6107 if (!NT_STATUS_IS_OK(status)) {
6108 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6109 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6110 smb_fname_str_dbg(smb_fname_dst)));
6111 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6112 status = NT_STATUS_ACCESS_DENIED;
6116 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6117 status = NT_STATUS_ACCESS_DENIED;
6120 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6124 * We have the file open ourselves, so not being able to get the
6125 * corresponding share mode lock is a fatal error.
6128 SMB_ASSERT(lck != NULL);
6130 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6131 uint32 create_options = fsp->fh->private_options;
6133 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6134 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6135 smb_fname_str_dbg(smb_fname_dst)));
6137 if (!lp_posix_pathnames() &&
6138 (lp_map_archive(SNUM(conn)) ||
6139 lp_store_dos_attributes(SNUM(conn)))) {
6140 /* We must set the archive bit on the newly
6142 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6143 uint32_t old_dosmode = dos_mode(conn,
6145 file_set_dosmode(conn,
6147 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6153 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6156 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6159 * A rename acts as a new file create w.r.t. allowing an initial delete
6160 * on close, probably because in Windows there is a new handle to the
6161 * new file. If initial delete on close was requested but not
6162 * originally set, we need to set it here. This is probably not 100% correct,
6163 * but will work for the CIFSFS client which in non-posix mode
6164 * depends on these semantics. JRA.
6167 if (create_options & FILE_DELETE_ON_CLOSE) {
6168 status = can_set_delete_on_close(fsp, 0);
6170 if (NT_STATUS_IS_OK(status)) {
6171 /* Note that here we set the *inital* delete on close flag,
6172 * not the regular one. The magic gets handled in close. */
6173 fsp->initial_delete_on_close = True;
6177 status = NT_STATUS_OK;
6183 if (errno == ENOTDIR || errno == EISDIR) {
6184 status = NT_STATUS_OBJECT_NAME_COLLISION;
6186 status = map_nt_error_from_unix(errno);
6189 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6190 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6191 smb_fname_str_dbg(smb_fname_dst)));
6194 TALLOC_FREE(smb_fname_dst);
6199 /****************************************************************************
6200 The guts of the rename command, split out so it may be called by the NT SMB
6202 ****************************************************************************/
6204 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6205 connection_struct *conn,
6206 struct smb_request *req,
6207 struct smb_filename *smb_fname_src,
6208 struct smb_filename *smb_fname_dst,
6210 bool replace_if_exists,
6213 uint32_t access_mask)
6215 char *fname_src_dir = NULL;
6216 char *fname_src_mask = NULL;
6218 NTSTATUS status = NT_STATUS_OK;
6219 struct smb_Dir *dir_hnd = NULL;
6220 const char *dname = NULL;
6221 char *talloced = NULL;
6223 int create_options = 0;
6224 bool posix_pathnames = lp_posix_pathnames();
6227 * Split the old name into directory and last component
6228 * strings. Note that unix_convert may have stripped off a
6229 * leading ./ from both name and newname if the rename is
6230 * at the root of the share. We need to make sure either both
6231 * name and newname contain a / character or neither of them do
6232 * as this is checked in resolve_wildcards().
6235 /* Split up the directory from the filename/mask. */
6236 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6237 &fname_src_dir, &fname_src_mask);
6238 if (!NT_STATUS_IS_OK(status)) {
6239 status = NT_STATUS_NO_MEMORY;
6244 * We should only check the mangled cache
6245 * here if unix_convert failed. This means
6246 * that the path in 'mask' doesn't exist
6247 * on the file system and so we need to look
6248 * for a possible mangle. This patch from
6249 * Tine Smukavec <valentin.smukavec@hermes.si>.
6252 if (!VALID_STAT(smb_fname_src->st) &&
6253 mangle_is_mangled(fname_src_mask, conn->params)) {
6254 char *new_mask = NULL;
6255 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6258 TALLOC_FREE(fname_src_mask);
6259 fname_src_mask = new_mask;
6263 if (!src_has_wild) {
6267 * Only one file needs to be renamed. Append the mask back
6268 * onto the directory.
6270 TALLOC_FREE(smb_fname_src->base_name);
6271 if (ISDOT(fname_src_dir)) {
6272 /* Ensure we use canonical names on open. */
6273 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6277 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6282 if (!smb_fname_src->base_name) {
6283 status = NT_STATUS_NO_MEMORY;
6287 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6288 "case_preserve = %d, short case preserve = %d, "
6289 "directory = %s, newname = %s, "
6290 "last_component_dest = %s\n",
6291 conn->case_sensitive, conn->case_preserve,
6292 conn->short_case_preserve,
6293 smb_fname_str_dbg(smb_fname_src),
6294 smb_fname_str_dbg(smb_fname_dst),
6295 smb_fname_dst->original_lcomp));
6297 /* The dest name still may have wildcards. */
6298 if (dest_has_wild) {
6299 char *fname_dst_mod = NULL;
6300 if (!resolve_wildcards(smb_fname_dst,
6301 smb_fname_src->base_name,
6302 smb_fname_dst->base_name,
6304 DEBUG(6, ("rename_internals: resolve_wildcards "
6306 smb_fname_src->base_name,
6307 smb_fname_dst->base_name));
6308 status = NT_STATUS_NO_MEMORY;
6311 TALLOC_FREE(smb_fname_dst->base_name);
6312 smb_fname_dst->base_name = fname_dst_mod;
6315 ZERO_STRUCT(smb_fname_src->st);
6316 if (posix_pathnames) {
6317 SMB_VFS_LSTAT(conn, smb_fname_src);
6319 SMB_VFS_STAT(conn, smb_fname_src);
6322 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6323 create_options |= FILE_DIRECTORY_FILE;
6326 status = SMB_VFS_CREATE_FILE(
6329 0, /* root_dir_fid */
6330 smb_fname_src, /* fname */
6331 access_mask, /* access_mask */
6332 (FILE_SHARE_READ | /* share_access */
6334 FILE_OPEN, /* create_disposition*/
6335 create_options, /* create_options */
6336 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6337 0, /* oplock_request */
6338 0, /* allocation_size */
6339 0, /* private_flags */
6345 if (!NT_STATUS_IS_OK(status)) {
6346 DEBUG(3, ("Could not open rename source %s: %s\n",
6347 smb_fname_str_dbg(smb_fname_src),
6348 nt_errstr(status)));
6352 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6353 attrs, replace_if_exists);
6355 close_file(req, fsp, NORMAL_CLOSE);
6357 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6358 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6359 smb_fname_str_dbg(smb_fname_dst)));
6365 * Wildcards - process each file that matches.
6367 if (strequal(fname_src_mask, "????????.???")) {
6368 TALLOC_FREE(fname_src_mask);
6369 fname_src_mask = talloc_strdup(ctx, "*");
6370 if (!fname_src_mask) {
6371 status = NT_STATUS_NO_MEMORY;
6376 status = check_name(conn, fname_src_dir);
6377 if (!NT_STATUS_IS_OK(status)) {
6381 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6383 if (dir_hnd == NULL) {
6384 status = map_nt_error_from_unix(errno);
6388 status = NT_STATUS_NO_SUCH_FILE;
6390 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6391 * - gentest fix. JRA
6394 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6396 files_struct *fsp = NULL;
6397 char *destname = NULL;
6398 bool sysdir_entry = False;
6400 /* Quick check for "." and ".." */
6401 if (ISDOT(dname) || ISDOTDOT(dname)) {
6403 sysdir_entry = True;
6405 TALLOC_FREE(talloced);
6410 if (!is_visible_file(conn, fname_src_dir, dname,
6411 &smb_fname_src->st, false)) {
6412 TALLOC_FREE(talloced);
6416 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6417 TALLOC_FREE(talloced);
6422 status = NT_STATUS_OBJECT_NAME_INVALID;
6426 TALLOC_FREE(smb_fname_src->base_name);
6427 if (ISDOT(fname_src_dir)) {
6428 /* Ensure we use canonical names on open. */
6429 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6433 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6438 if (!smb_fname_src->base_name) {
6439 status = NT_STATUS_NO_MEMORY;
6443 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6444 smb_fname_dst->base_name,
6446 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6447 smb_fname_src->base_name, destname));
6448 TALLOC_FREE(talloced);
6452 status = NT_STATUS_NO_MEMORY;
6456 TALLOC_FREE(smb_fname_dst->base_name);
6457 smb_fname_dst->base_name = destname;
6459 ZERO_STRUCT(smb_fname_src->st);
6460 if (posix_pathnames) {
6461 SMB_VFS_LSTAT(conn, smb_fname_src);
6463 SMB_VFS_STAT(conn, smb_fname_src);
6468 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6469 create_options |= FILE_DIRECTORY_FILE;
6472 status = SMB_VFS_CREATE_FILE(
6475 0, /* root_dir_fid */
6476 smb_fname_src, /* fname */
6477 access_mask, /* access_mask */
6478 (FILE_SHARE_READ | /* share_access */
6480 FILE_OPEN, /* create_disposition*/
6481 create_options, /* create_options */
6482 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6483 0, /* oplock_request */
6484 0, /* allocation_size */
6485 0, /* private_flags */
6491 if (!NT_STATUS_IS_OK(status)) {
6492 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6493 "returned %s rename %s -> %s\n",
6495 smb_fname_str_dbg(smb_fname_src),
6496 smb_fname_str_dbg(smb_fname_dst)));
6500 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6502 if (!smb_fname_dst->original_lcomp) {
6503 status = NT_STATUS_NO_MEMORY;
6507 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6508 attrs, replace_if_exists);
6510 close_file(req, fsp, NORMAL_CLOSE);
6512 if (!NT_STATUS_IS_OK(status)) {
6513 DEBUG(3, ("rename_internals_fsp returned %s for "
6514 "rename %s -> %s\n", nt_errstr(status),
6515 smb_fname_str_dbg(smb_fname_src),
6516 smb_fname_str_dbg(smb_fname_dst)));
6522 DEBUG(3,("rename_internals: doing rename on %s -> "
6523 "%s\n", smb_fname_str_dbg(smb_fname_src),
6524 smb_fname_str_dbg(smb_fname_src)));
6525 TALLOC_FREE(talloced);
6527 TALLOC_FREE(dir_hnd);
6529 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6530 status = map_nt_error_from_unix(errno);
6534 TALLOC_FREE(talloced);
6535 TALLOC_FREE(fname_src_dir);
6536 TALLOC_FREE(fname_src_mask);
6540 /****************************************************************************
6542 ****************************************************************************/
6544 void reply_mv(struct smb_request *req)
6546 connection_struct *conn = req->conn;
6548 char *newname = NULL;
6552 bool src_has_wcard = False;
6553 bool dest_has_wcard = False;
6554 TALLOC_CTX *ctx = talloc_tos();
6555 struct smb_filename *smb_fname_src = NULL;
6556 struct smb_filename *smb_fname_dst = NULL;
6557 bool stream_rename = false;
6559 START_PROFILE(SMBmv);
6562 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6566 attrs = SVAL(req->vwv+0, 0);
6568 p = (const char *)req->buf + 1;
6569 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6570 &status, &src_has_wcard);
6571 if (!NT_STATUS_IS_OK(status)) {
6572 reply_nterror(req, status);
6576 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6577 &status, &dest_has_wcard);
6578 if (!NT_STATUS_IS_OK(status)) {
6579 reply_nterror(req, status);
6583 if (!lp_posix_pathnames()) {
6584 /* The newname must begin with a ':' if the
6585 name contains a ':'. */
6586 if (strchr_m(name, ':')) {
6587 if (newname[0] != ':') {
6588 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6591 stream_rename = true;
6595 status = filename_convert(ctx,
6597 req->flags2 & FLAGS2_DFS_PATHNAMES,
6599 UCF_COND_ALLOW_WCARD_LCOMP,
6603 if (!NT_STATUS_IS_OK(status)) {
6604 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6605 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6606 ERRSRV, ERRbadpath);
6609 reply_nterror(req, status);
6613 status = filename_convert(ctx,
6615 req->flags2 & FLAGS2_DFS_PATHNAMES,
6617 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6621 if (!NT_STATUS_IS_OK(status)) {
6622 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6623 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6624 ERRSRV, ERRbadpath);
6627 reply_nterror(req, status);
6631 if (stream_rename) {
6632 /* smb_fname_dst->base_name must be the same as
6633 smb_fname_src->base_name. */
6634 TALLOC_FREE(smb_fname_dst->base_name);
6635 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6636 smb_fname_src->base_name);
6637 if (!smb_fname_dst->base_name) {
6638 reply_nterror(req, NT_STATUS_NO_MEMORY);
6643 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6644 smb_fname_str_dbg(smb_fname_dst)));
6646 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6647 attrs, False, src_has_wcard, dest_has_wcard,
6649 if (!NT_STATUS_IS_OK(status)) {
6650 if (open_was_deferred(req->mid)) {
6651 /* We have re-scheduled this call. */
6654 reply_nterror(req, status);
6658 reply_outbuf(req, 0, 0);
6660 TALLOC_FREE(smb_fname_src);
6661 TALLOC_FREE(smb_fname_dst);
6666 /*******************************************************************
6667 Copy a file as part of a reply_copy.
6668 ******************************************************************/
6671 * TODO: check error codes on all callers
6674 NTSTATUS copy_file(TALLOC_CTX *ctx,
6675 connection_struct *conn,
6676 struct smb_filename *smb_fname_src,
6677 struct smb_filename *smb_fname_dst,
6680 bool target_is_directory)
6682 struct smb_filename *smb_fname_dst_tmp = NULL;
6684 files_struct *fsp1,*fsp2;
6686 uint32 new_create_disposition;
6690 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6691 if (!NT_STATUS_IS_OK(status)) {
6696 * If the target is a directory, extract the last component from the
6697 * src filename and append it to the dst filename
6699 if (target_is_directory) {
6702 /* dest/target can't be a stream if it's a directory. */
6703 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6705 p = strrchr_m(smb_fname_src->base_name,'/');
6709 p = smb_fname_src->base_name;
6711 smb_fname_dst_tmp->base_name =
6712 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6714 if (!smb_fname_dst_tmp->base_name) {
6715 status = NT_STATUS_NO_MEMORY;
6720 status = vfs_file_exist(conn, smb_fname_src);
6721 if (!NT_STATUS_IS_OK(status)) {
6725 if (!target_is_directory && count) {
6726 new_create_disposition = FILE_OPEN;
6728 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6730 &new_create_disposition,
6733 status = NT_STATUS_INVALID_PARAMETER;
6738 /* Open the src file for reading. */
6739 status = SMB_VFS_CREATE_FILE(
6742 0, /* root_dir_fid */
6743 smb_fname_src, /* fname */
6744 FILE_GENERIC_READ, /* access_mask */
6745 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6746 FILE_OPEN, /* create_disposition*/
6747 0, /* create_options */
6748 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6749 INTERNAL_OPEN_ONLY, /* oplock_request */
6750 0, /* allocation_size */
6751 0, /* private_flags */
6757 if (!NT_STATUS_IS_OK(status)) {
6761 dosattrs = dos_mode(conn, smb_fname_src);
6763 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6764 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6767 /* Open the dst file for writing. */
6768 status = SMB_VFS_CREATE_FILE(
6771 0, /* root_dir_fid */
6772 smb_fname_dst, /* fname */
6773 FILE_GENERIC_WRITE, /* access_mask */
6774 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6775 new_create_disposition, /* create_disposition*/
6776 0, /* create_options */
6777 dosattrs, /* file_attributes */
6778 INTERNAL_OPEN_ONLY, /* oplock_request */
6779 0, /* allocation_size */
6780 0, /* private_flags */
6786 if (!NT_STATUS_IS_OK(status)) {
6787 close_file(NULL, fsp1, ERROR_CLOSE);
6791 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6792 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6794 DEBUG(0, ("error - vfs lseek returned error %s\n",
6796 status = map_nt_error_from_unix(errno);
6797 close_file(NULL, fsp1, ERROR_CLOSE);
6798 close_file(NULL, fsp2, ERROR_CLOSE);
6803 /* Do the actual copy. */
6804 if (smb_fname_src->st.st_ex_size) {
6805 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6810 close_file(NULL, fsp1, NORMAL_CLOSE);
6812 /* Ensure the modtime is set correctly on the destination file. */
6813 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6816 * As we are opening fsp1 read-only we only expect
6817 * an error on close on fsp2 if we are out of space.
6818 * Thus we don't look at the error return from the
6821 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6823 if (!NT_STATUS_IS_OK(status)) {
6827 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6828 status = NT_STATUS_DISK_FULL;
6832 status = NT_STATUS_OK;
6835 TALLOC_FREE(smb_fname_dst_tmp);
6839 /****************************************************************************
6840 Reply to a file copy.
6841 ****************************************************************************/
6843 void reply_copy(struct smb_request *req)
6845 connection_struct *conn = req->conn;
6846 struct smb_filename *smb_fname_src = NULL;
6847 struct smb_filename *smb_fname_dst = NULL;
6848 char *fname_src = NULL;
6849 char *fname_dst = NULL;
6850 char *fname_src_mask = NULL;
6851 char *fname_src_dir = NULL;
6854 int error = ERRnoaccess;
6858 bool target_is_directory=False;
6859 bool source_has_wild = False;
6860 bool dest_has_wild = False;
6862 TALLOC_CTX *ctx = talloc_tos();
6864 START_PROFILE(SMBcopy);
6867 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6871 tid2 = SVAL(req->vwv+0, 0);
6872 ofun = SVAL(req->vwv+1, 0);
6873 flags = SVAL(req->vwv+2, 0);
6875 p = (const char *)req->buf;
6876 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6877 &status, &source_has_wild);
6878 if (!NT_STATUS_IS_OK(status)) {
6879 reply_nterror(req, status);
6882 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6883 &status, &dest_has_wild);
6884 if (!NT_STATUS_IS_OK(status)) {
6885 reply_nterror(req, status);
6889 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6891 if (tid2 != conn->cnum) {
6892 /* can't currently handle inter share copies XXXX */
6893 DEBUG(3,("Rejecting inter-share copy\n"));
6894 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6898 status = filename_convert(ctx, conn,
6899 req->flags2 & FLAGS2_DFS_PATHNAMES,
6901 UCF_COND_ALLOW_WCARD_LCOMP,
6904 if (!NT_STATUS_IS_OK(status)) {
6905 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6906 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6907 ERRSRV, ERRbadpath);
6910 reply_nterror(req, status);
6914 status = filename_convert(ctx, conn,
6915 req->flags2 & FLAGS2_DFS_PATHNAMES,
6917 UCF_COND_ALLOW_WCARD_LCOMP,
6920 if (!NT_STATUS_IS_OK(status)) {
6921 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6922 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6923 ERRSRV, ERRbadpath);
6926 reply_nterror(req, status);
6930 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6932 if ((flags&1) && target_is_directory) {
6933 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6937 if ((flags&2) && !target_is_directory) {
6938 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6942 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6943 /* wants a tree copy! XXXX */
6944 DEBUG(3,("Rejecting tree copy\n"));
6945 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6949 /* Split up the directory from the filename/mask. */
6950 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6951 &fname_src_dir, &fname_src_mask);
6952 if (!NT_STATUS_IS_OK(status)) {
6953 reply_nterror(req, NT_STATUS_NO_MEMORY);
6958 * We should only check the mangled cache
6959 * here if unix_convert failed. This means
6960 * that the path in 'mask' doesn't exist
6961 * on the file system and so we need to look
6962 * for a possible mangle. This patch from
6963 * Tine Smukavec <valentin.smukavec@hermes.si>.
6965 if (!VALID_STAT(smb_fname_src->st) &&
6966 mangle_is_mangled(fname_src_mask, conn->params)) {
6967 char *new_mask = NULL;
6968 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6969 &new_mask, conn->params);
6971 /* Use demangled name if one was successfully found. */
6973 TALLOC_FREE(fname_src_mask);
6974 fname_src_mask = new_mask;
6978 if (!source_has_wild) {
6981 * Only one file needs to be copied. Append the mask back onto
6984 TALLOC_FREE(smb_fname_src->base_name);
6985 if (ISDOT(fname_src_dir)) {
6986 /* Ensure we use canonical names on open. */
6987 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6991 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6996 if (!smb_fname_src->base_name) {
6997 reply_nterror(req, NT_STATUS_NO_MEMORY);
7001 if (dest_has_wild) {
7002 char *fname_dst_mod = NULL;
7003 if (!resolve_wildcards(smb_fname_dst,
7004 smb_fname_src->base_name,
7005 smb_fname_dst->base_name,
7007 reply_nterror(req, NT_STATUS_NO_MEMORY);
7010 TALLOC_FREE(smb_fname_dst->base_name);
7011 smb_fname_dst->base_name = fname_dst_mod;
7014 status = check_name(conn, smb_fname_src->base_name);
7015 if (!NT_STATUS_IS_OK(status)) {
7016 reply_nterror(req, status);
7020 status = check_name(conn, smb_fname_dst->base_name);
7021 if (!NT_STATUS_IS_OK(status)) {
7022 reply_nterror(req, status);
7026 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7027 ofun, count, target_is_directory);
7029 if(!NT_STATUS_IS_OK(status)) {
7030 reply_nterror(req, status);
7036 struct smb_Dir *dir_hnd = NULL;
7037 const char *dname = NULL;
7038 char *talloced = NULL;
7042 * There is a wildcard that requires us to actually read the
7043 * src dir and copy each file matching the mask to the dst.
7044 * Right now streams won't be copied, but this could
7045 * presumably be added with a nested loop for reach dir entry.
7047 SMB_ASSERT(!smb_fname_src->stream_name);
7048 SMB_ASSERT(!smb_fname_dst->stream_name);
7050 smb_fname_src->stream_name = NULL;
7051 smb_fname_dst->stream_name = NULL;
7053 if (strequal(fname_src_mask,"????????.???")) {
7054 TALLOC_FREE(fname_src_mask);
7055 fname_src_mask = talloc_strdup(ctx, "*");
7056 if (!fname_src_mask) {
7057 reply_nterror(req, NT_STATUS_NO_MEMORY);
7062 status = check_name(conn, fname_src_dir);
7063 if (!NT_STATUS_IS_OK(status)) {
7064 reply_nterror(req, status);
7068 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7069 if (dir_hnd == NULL) {
7070 status = map_nt_error_from_unix(errno);
7071 reply_nterror(req, status);
7077 /* Iterate over the src dir copying each entry to the dst. */
7078 while ((dname = ReadDirName(dir_hnd, &offset,
7079 &smb_fname_src->st, &talloced))) {
7080 char *destname = NULL;
7082 if (ISDOT(dname) || ISDOTDOT(dname)) {
7083 TALLOC_FREE(talloced);
7087 if (!is_visible_file(conn, fname_src_dir, dname,
7088 &smb_fname_src->st, false)) {
7089 TALLOC_FREE(talloced);
7093 if(!mask_match(dname, fname_src_mask,
7094 conn->case_sensitive)) {
7095 TALLOC_FREE(talloced);
7099 error = ERRnoaccess;
7101 /* Get the src smb_fname struct setup. */
7102 TALLOC_FREE(smb_fname_src->base_name);
7103 if (ISDOT(fname_src_dir)) {
7104 /* Ensure we use canonical names on open. */
7105 smb_fname_src->base_name =
7106 talloc_asprintf(smb_fname_src, "%s",
7109 smb_fname_src->base_name =
7110 talloc_asprintf(smb_fname_src, "%s/%s",
7111 fname_src_dir, dname);
7114 if (!smb_fname_src->base_name) {
7115 TALLOC_FREE(dir_hnd);
7116 TALLOC_FREE(talloced);
7117 reply_nterror(req, NT_STATUS_NO_MEMORY);
7121 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7122 smb_fname_dst->base_name,
7124 TALLOC_FREE(talloced);
7128 TALLOC_FREE(dir_hnd);
7129 TALLOC_FREE(talloced);
7130 reply_nterror(req, NT_STATUS_NO_MEMORY);
7134 TALLOC_FREE(smb_fname_dst->base_name);
7135 smb_fname_dst->base_name = destname;
7137 status = check_name(conn, smb_fname_src->base_name);
7138 if (!NT_STATUS_IS_OK(status)) {
7139 TALLOC_FREE(dir_hnd);
7140 TALLOC_FREE(talloced);
7141 reply_nterror(req, status);
7145 status = check_name(conn, smb_fname_dst->base_name);
7146 if (!NT_STATUS_IS_OK(status)) {
7147 TALLOC_FREE(dir_hnd);
7148 TALLOC_FREE(talloced);
7149 reply_nterror(req, status);
7153 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7154 smb_fname_src->base_name,
7155 smb_fname_dst->base_name));
7157 status = copy_file(ctx, conn, smb_fname_src,
7158 smb_fname_dst, ofun, count,
7159 target_is_directory);
7160 if (NT_STATUS_IS_OK(status)) {
7164 TALLOC_FREE(talloced);
7166 TALLOC_FREE(dir_hnd);
7170 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7174 reply_outbuf(req, 1, 0);
7175 SSVAL(req->outbuf,smb_vwv0,count);
7177 TALLOC_FREE(smb_fname_src);
7178 TALLOC_FREE(smb_fname_dst);
7179 TALLOC_FREE(fname_src);
7180 TALLOC_FREE(fname_dst);
7181 TALLOC_FREE(fname_src_mask);
7182 TALLOC_FREE(fname_src_dir);
7184 END_PROFILE(SMBcopy);
7189 #define DBGC_CLASS DBGC_LOCKING
7191 /****************************************************************************
7192 Get a lock pid, dealing with large count requests.
7193 ****************************************************************************/
7195 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7196 bool large_file_format)
7198 if(!large_file_format)
7199 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7201 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7204 /****************************************************************************
7205 Get a lock count, dealing with large count requests.
7206 ****************************************************************************/
7208 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7209 bool large_file_format)
7213 if(!large_file_format) {
7214 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7217 #if defined(HAVE_LONGLONG)
7218 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7219 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7220 #else /* HAVE_LONGLONG */
7223 * NT4.x seems to be broken in that it sends large file (64 bit)
7224 * lockingX calls even if the CAP_LARGE_FILES was *not*
7225 * negotiated. For boxes without large unsigned ints truncate the
7226 * lock count by dropping the top 32 bits.
7229 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7230 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7231 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7232 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7233 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7236 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7237 #endif /* HAVE_LONGLONG */
7243 #if !defined(HAVE_LONGLONG)
7244 /****************************************************************************
7245 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7246 ****************************************************************************/
7248 static uint32 map_lock_offset(uint32 high, uint32 low)
7252 uint32 highcopy = high;
7255 * Try and find out how many significant bits there are in high.
7258 for(i = 0; highcopy; i++)
7262 * We use 31 bits not 32 here as POSIX
7263 * lock offsets may not be negative.
7266 mask = (~0) << (31 - i);
7269 return 0; /* Fail. */
7275 #endif /* !defined(HAVE_LONGLONG) */
7277 /****************************************************************************
7278 Get a lock offset, dealing with large offset requests.
7279 ****************************************************************************/
7281 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7282 bool large_file_format, bool *err)
7284 uint64_t offset = 0;
7288 if(!large_file_format) {
7289 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7292 #if defined(HAVE_LONGLONG)
7293 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7294 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7295 #else /* HAVE_LONGLONG */
7298 * NT4.x seems to be broken in that it sends large file (64 bit)
7299 * lockingX calls even if the CAP_LARGE_FILES was *not*
7300 * negotiated. For boxes without large unsigned ints mangle the
7301 * lock offset by mapping the top 32 bits onto the lower 32.
7304 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7305 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7306 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7309 if((new_low = map_lock_offset(high, low)) == 0) {
7311 return (uint64_t)-1;
7314 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7315 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7316 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7317 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7320 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7321 #endif /* HAVE_LONGLONG */
7327 NTSTATUS smbd_do_locking(struct smb_request *req,
7331 uint16_t num_ulocks,
7332 struct smbd_lock_element *ulocks,
7334 struct smbd_lock_element *locks,
7337 connection_struct *conn = req->conn;
7339 NTSTATUS status = NT_STATUS_OK;
7343 /* Data now points at the beginning of the list
7344 of smb_unlkrng structs */
7345 for(i = 0; i < (int)num_ulocks; i++) {
7346 struct smbd_lock_element *e = &ulocks[i];
7348 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7349 "pid %u, file %s\n",
7352 (unsigned int)e->smblctx,
7355 if (e->brltype != UNLOCK_LOCK) {
7356 /* this can only happen with SMB2 */
7357 return NT_STATUS_INVALID_PARAMETER;
7360 status = do_unlock(req->sconn->msg_ctx,
7367 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7368 nt_errstr(status)));
7370 if (!NT_STATUS_IS_OK(status)) {
7375 /* Setup the timeout in seconds. */
7377 if (!lp_blocking_locks(SNUM(conn))) {
7381 /* Data now points at the beginning of the list
7382 of smb_lkrng structs */
7384 for(i = 0; i < (int)num_locks; i++) {
7385 struct smbd_lock_element *e = &locks[i];
7387 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7388 "%llu, file %s timeout = %d\n",
7391 (unsigned long long)e->smblctx,
7395 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7396 struct blocking_lock_record *blr = NULL;
7398 if (num_locks > 1) {
7400 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7401 * if the lock vector contains one entry. When given mutliple cancel
7402 * requests in a single PDU we expect the server to return an
7403 * error. Windows servers seem to accept the request but only
7404 * cancel the first lock.
7405 * JRA - Do what Windows does (tm) :-).
7409 /* MS-CIFS (2.2.4.32.1) behavior. */
7410 return NT_STATUS_DOS(ERRDOS,
7411 ERRcancelviolation);
7413 /* Windows behavior. */
7415 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7416 "cancel request\n"));
7422 if (lp_blocking_locks(SNUM(conn))) {
7424 /* Schedule a message to ourselves to
7425 remove the blocking lock record and
7426 return the right error. */
7428 blr = blocking_lock_cancel_smb1(fsp,
7434 NT_STATUS_FILE_LOCK_CONFLICT);
7436 return NT_STATUS_DOS(
7438 ERRcancelviolation);
7441 /* Remove a matching pending lock. */
7442 status = do_lock_cancel(fsp,
7449 bool blocking_lock = timeout ? true : false;
7450 bool defer_lock = false;
7451 struct byte_range_lock *br_lck;
7452 uint64_t block_smblctx;
7454 br_lck = do_lock(req->sconn->msg_ctx,
7466 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7467 /* Windows internal resolution for blocking locks seems
7468 to be about 200ms... Don't wait for less than that. JRA. */
7469 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7470 timeout = lp_lock_spin_time();
7475 /* If a lock sent with timeout of zero would fail, and
7476 * this lock has been requested multiple times,
7477 * according to brl_lock_failed() we convert this
7478 * request to a blocking lock with a timeout of between
7479 * 150 - 300 milliseconds.
7481 * If lp_lock_spin_time() has been set to 0, we skip
7482 * this blocking retry and fail immediately.
7484 * Replacement for do_lock_spin(). JRA. */
7486 if (!req->sconn->using_smb2 &&
7487 br_lck && lp_blocking_locks(SNUM(conn)) &&
7488 lp_lock_spin_time() && !blocking_lock &&
7489 NT_STATUS_EQUAL((status),
7490 NT_STATUS_FILE_LOCK_CONFLICT))
7493 timeout = lp_lock_spin_time();
7496 if (br_lck && defer_lock) {
7498 * A blocking lock was requested. Package up
7499 * this smb into a queued request and push it
7500 * onto the blocking lock queue.
7502 if(push_blocking_lock_request(br_lck,
7513 TALLOC_FREE(br_lck);
7515 return NT_STATUS_OK;
7519 TALLOC_FREE(br_lck);
7522 if (!NT_STATUS_IS_OK(status)) {
7527 /* If any of the above locks failed, then we must unlock
7528 all of the previous locks (X/Open spec). */
7530 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7532 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7533 i = -1; /* we want to skip the for loop */
7537 * Ensure we don't do a remove on the lock that just failed,
7538 * as under POSIX rules, if we have a lock already there, we
7539 * will delete it (and we shouldn't) .....
7541 for(i--; i >= 0; i--) {
7542 struct smbd_lock_element *e = &locks[i];
7544 do_unlock(req->sconn->msg_ctx,
7554 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7555 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7557 return NT_STATUS_OK;
7560 /****************************************************************************
7561 Reply to a lockingX request.
7562 ****************************************************************************/
7564 void reply_lockingX(struct smb_request *req)
7566 connection_struct *conn = req->conn;
7568 unsigned char locktype;
7569 unsigned char oplocklevel;
7574 const uint8_t *data;
7575 bool large_file_format;
7577 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7578 struct smbd_lock_element *ulocks;
7579 struct smbd_lock_element *locks;
7582 START_PROFILE(SMBlockingX);
7585 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7586 END_PROFILE(SMBlockingX);
7590 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7591 locktype = CVAL(req->vwv+3, 0);
7592 oplocklevel = CVAL(req->vwv+3, 1);
7593 num_ulocks = SVAL(req->vwv+6, 0);
7594 num_locks = SVAL(req->vwv+7, 0);
7595 lock_timeout = IVAL(req->vwv+4, 0);
7596 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7598 if (!check_fsp(conn, req, fsp)) {
7599 END_PROFILE(SMBlockingX);
7605 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7606 /* we don't support these - and CANCEL_LOCK makes w2k
7607 and XP reboot so I don't really want to be
7608 compatible! (tridge) */
7609 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7610 END_PROFILE(SMBlockingX);
7614 /* Check if this is an oplock break on a file
7615 we have granted an oplock on.
7617 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7618 /* Client can insist on breaking to none. */
7619 bool break_to_none = (oplocklevel == 0);
7622 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7623 "for fnum = %d\n", (unsigned int)oplocklevel,
7627 * Make sure we have granted an exclusive or batch oplock on
7631 if (fsp->oplock_type == 0) {
7633 /* The Samba4 nbench simulator doesn't understand
7634 the difference between break to level2 and break
7635 to none from level2 - it sends oplock break
7636 replies in both cases. Don't keep logging an error
7637 message here - just ignore it. JRA. */
7639 DEBUG(5,("reply_lockingX: Error : oplock break from "
7640 "client for fnum = %d (oplock=%d) and no "
7641 "oplock granted on this file (%s).\n",
7642 fsp->fnum, fsp->oplock_type,
7645 /* if this is a pure oplock break request then don't
7647 if (num_locks == 0 && num_ulocks == 0) {
7648 END_PROFILE(SMBlockingX);
7651 END_PROFILE(SMBlockingX);
7652 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7657 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7659 result = remove_oplock(fsp);
7661 result = downgrade_oplock(fsp);
7665 DEBUG(0, ("reply_lockingX: error in removing "
7666 "oplock on file %s\n", fsp_str_dbg(fsp)));
7667 /* Hmmm. Is this panic justified? */
7668 smb_panic("internal tdb error");
7671 reply_to_oplock_break_requests(fsp);
7673 /* if this is a pure oplock break request then don't send a
7675 if (num_locks == 0 && num_ulocks == 0) {
7676 /* Sanity check - ensure a pure oplock break is not a
7678 if(CVAL(req->vwv+0, 0) != 0xff)
7679 DEBUG(0,("reply_lockingX: Error : pure oplock "
7680 "break is a chained %d request !\n",
7681 (unsigned int)CVAL(req->vwv+0, 0)));
7682 END_PROFILE(SMBlockingX);
7688 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7689 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7690 END_PROFILE(SMBlockingX);
7694 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7695 if (ulocks == NULL) {
7696 reply_nterror(req, NT_STATUS_NO_MEMORY);
7697 END_PROFILE(SMBlockingX);
7701 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7702 if (locks == NULL) {
7703 reply_nterror(req, NT_STATUS_NO_MEMORY);
7704 END_PROFILE(SMBlockingX);
7708 /* Data now points at the beginning of the list
7709 of smb_unlkrng structs */
7710 for(i = 0; i < (int)num_ulocks; i++) {
7711 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7712 ulocks[i].count = get_lock_count(data, i, large_file_format);
7713 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7714 ulocks[i].brltype = UNLOCK_LOCK;
7717 * There is no error code marked "stupid client bug".... :-).
7720 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7721 END_PROFILE(SMBlockingX);
7726 /* Now do any requested locks */
7727 data += ((large_file_format ? 20 : 10)*num_ulocks);
7729 /* Data now points at the beginning of the list
7730 of smb_lkrng structs */
7732 for(i = 0; i < (int)num_locks; i++) {
7733 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7734 locks[i].count = get_lock_count(data, i, large_file_format);
7735 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7737 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7738 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7739 locks[i].brltype = PENDING_READ_LOCK;
7741 locks[i].brltype = READ_LOCK;
7744 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7745 locks[i].brltype = PENDING_WRITE_LOCK;
7747 locks[i].brltype = WRITE_LOCK;
7752 * There is no error code marked "stupid client bug".... :-).
7755 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7756 END_PROFILE(SMBlockingX);
7761 status = smbd_do_locking(req, fsp,
7762 locktype, lock_timeout,
7766 if (!NT_STATUS_IS_OK(status)) {
7767 END_PROFILE(SMBlockingX);
7768 reply_nterror(req, status);
7772 END_PROFILE(SMBlockingX);
7776 reply_outbuf(req, 2, 0);
7778 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7779 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7781 END_PROFILE(SMBlockingX);
7786 #define DBGC_CLASS DBGC_ALL
7788 /****************************************************************************
7789 Reply to a SMBreadbmpx (read block multiplex) request.
7790 Always reply with an error, if someone has a platform really needs this,
7791 please contact vl@samba.org
7792 ****************************************************************************/
7794 void reply_readbmpx(struct smb_request *req)
7796 START_PROFILE(SMBreadBmpx);
7797 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7798 END_PROFILE(SMBreadBmpx);
7802 /****************************************************************************
7803 Reply to a SMBreadbs (read block multiplex secondary) request.
7804 Always reply with an error, if someone has a platform really needs this,
7805 please contact vl@samba.org
7806 ****************************************************************************/
7808 void reply_readbs(struct smb_request *req)
7810 START_PROFILE(SMBreadBs);
7811 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7812 END_PROFILE(SMBreadBs);
7816 /****************************************************************************
7817 Reply to a SMBsetattrE.
7818 ****************************************************************************/
7820 void reply_setattrE(struct smb_request *req)
7822 connection_struct *conn = req->conn;
7823 struct smb_file_time ft;
7827 START_PROFILE(SMBsetattrE);
7831 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7835 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7837 if(!fsp || (fsp->conn != conn)) {
7838 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7843 * Convert the DOS times into unix times.
7846 ft.atime = convert_time_t_to_timespec(
7847 srv_make_unix_date2(req->vwv+3));
7848 ft.mtime = convert_time_t_to_timespec(
7849 srv_make_unix_date2(req->vwv+5));
7850 ft.create_time = convert_time_t_to_timespec(
7851 srv_make_unix_date2(req->vwv+1));
7853 reply_outbuf(req, 0, 0);
7856 * Patch from Ray Frush <frush@engr.colostate.edu>
7857 * Sometimes times are sent as zero - ignore them.
7860 /* Ensure we have a valid stat struct for the source. */
7861 status = vfs_stat_fsp(fsp);
7862 if (!NT_STATUS_IS_OK(status)) {
7863 reply_nterror(req, status);
7867 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7868 if (!NT_STATUS_IS_OK(status)) {
7869 reply_nterror(req, status);
7873 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7876 (unsigned int)ft.atime.tv_sec,
7877 (unsigned int)ft.mtime.tv_sec,
7878 (unsigned int)ft.create_time.tv_sec
7881 END_PROFILE(SMBsetattrE);
7886 /* Back from the dead for OS/2..... JRA. */
7888 /****************************************************************************
7889 Reply to a SMBwritebmpx (write block multiplex primary) request.
7890 Always reply with an error, if someone has a platform really needs this,
7891 please contact vl@samba.org
7892 ****************************************************************************/
7894 void reply_writebmpx(struct smb_request *req)
7896 START_PROFILE(SMBwriteBmpx);
7897 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7898 END_PROFILE(SMBwriteBmpx);
7902 /****************************************************************************
7903 Reply to a SMBwritebs (write block multiplex secondary) request.
7904 Always reply with an error, if someone has a platform really needs this,
7905 please contact vl@samba.org
7906 ****************************************************************************/
7908 void reply_writebs(struct smb_request *req)
7910 START_PROFILE(SMBwriteBs);
7911 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7912 END_PROFILE(SMBwriteBs);
7916 /****************************************************************************
7917 Reply to a SMBgetattrE.
7918 ****************************************************************************/
7920 void reply_getattrE(struct smb_request *req)
7922 connection_struct *conn = req->conn;
7925 struct timespec create_ts;
7927 START_PROFILE(SMBgetattrE);
7930 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7931 END_PROFILE(SMBgetattrE);
7935 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7937 if(!fsp || (fsp->conn != conn)) {
7938 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7939 END_PROFILE(SMBgetattrE);
7943 /* Do an fstat on this file */
7945 reply_nterror(req, map_nt_error_from_unix(errno));
7946 END_PROFILE(SMBgetattrE);
7950 mode = dos_mode(conn, fsp->fsp_name);
7953 * Convert the times into dos times. Set create
7954 * date to be last modify date as UNIX doesn't save
7958 reply_outbuf(req, 11, 0);
7960 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7961 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7962 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7963 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7964 /* Should we check pending modtime here ? JRA */
7965 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7966 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7969 SIVAL(req->outbuf, smb_vwv6, 0);
7970 SIVAL(req->outbuf, smb_vwv8, 0);
7972 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7973 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7974 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7976 SSVAL(req->outbuf,smb_vwv10, mode);
7978 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7980 END_PROFILE(SMBgetattrE);