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/globals.h"
31 #include "fake_file.h"
32 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
33 #include "rpc_client/cli_spoolss.h"
34 #include "rpc_client/init_spoolss.h"
35 #include "rpc_server/rpc_ncacn_np.h"
36 #include "libcli/security/security.h"
38 /****************************************************************************
39 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
40 path or anything including wildcards.
41 We're assuming here that '/' is not the second byte in any multibyte char
42 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
44 ****************************************************************************/
46 /* Custom version for processing POSIX paths. */
47 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
49 static NTSTATUS check_path_syntax_internal(char *path,
51 bool *p_last_component_contains_wcard)
55 NTSTATUS ret = NT_STATUS_OK;
56 bool start_of_name_component = True;
57 bool stream_started = false;
59 *p_last_component_contains_wcard = False;
66 return NT_STATUS_OBJECT_NAME_INVALID;
69 return NT_STATUS_OBJECT_NAME_INVALID;
71 if (strchr_m(&s[1], ':')) {
72 return NT_STATUS_OBJECT_NAME_INVALID;
78 if ((*s == ':') && !posix_path && !stream_started) {
79 if (*p_last_component_contains_wcard) {
80 return NT_STATUS_OBJECT_NAME_INVALID;
82 /* Stream names allow more characters than file names.
83 We're overloading posix_path here to allow a wider
84 range of characters. If stream_started is true this
85 is still a Windows path even if posix_path is true.
88 stream_started = true;
89 start_of_name_component = false;
93 return NT_STATUS_OBJECT_NAME_INVALID;
97 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
99 * Safe to assume is not the second part of a mb char
100 * as this is handled below.
102 /* Eat multiple '/' or '\\' */
103 while (IS_PATH_SEP(*s,posix_path)) {
106 if ((d != path) && (*s != '\0')) {
107 /* We only care about non-leading or trailing '/' or '\\' */
111 start_of_name_component = True;
113 *p_last_component_contains_wcard = False;
117 if (start_of_name_component) {
118 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
119 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
122 * No mb char starts with '.' so we're safe checking the directory separator here.
125 /* If we just added a '/' - delete it */
126 if ((d > path) && (*(d-1) == '/')) {
131 /* Are we at the start ? Can't go back further if so. */
133 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
136 /* Go back one level... */
137 /* We know this is safe as '/' cannot be part of a mb sequence. */
138 /* NOTE - if this assumption is invalid we are not in good shape... */
139 /* Decrement d first as d points to the *next* char to write into. */
140 for (d--; d > path; d--) {
144 s += 2; /* Else go past the .. */
145 /* We're still at the start of a name component, just the previous one. */
148 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
160 if (*s <= 0x1f || *s == '|') {
161 return NT_STATUS_OBJECT_NAME_INVALID;
169 *p_last_component_contains_wcard = True;
178 /* Get the size of the next MB character. */
179 next_codepoint(s,&siz);
197 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
199 return NT_STATUS_INVALID_PARAMETER;
202 start_of_name_component = False;
210 /****************************************************************************
211 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
212 No wildcards allowed.
213 ****************************************************************************/
215 NTSTATUS check_path_syntax(char *path)
218 return check_path_syntax_internal(path, False, &ignore);
221 /****************************************************************************
222 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
223 Wildcards allowed - p_contains_wcard returns true if the last component contained
225 ****************************************************************************/
227 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
229 return check_path_syntax_internal(path, False, p_contains_wcard);
232 /****************************************************************************
233 Check the path for a POSIX client.
234 We're assuming here that '/' is not the second byte in any multibyte char
235 set (a safe assumption).
236 ****************************************************************************/
238 NTSTATUS check_path_syntax_posix(char *path)
241 return check_path_syntax_internal(path, True, &ignore);
244 /****************************************************************************
245 Pull a string and check the path allowing a wilcard - provide for error return.
246 ****************************************************************************/
248 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
249 const char *base_ptr,
256 bool *contains_wcard)
262 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
266 *err = NT_STATUS_INVALID_PARAMETER;
270 *contains_wcard = False;
272 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
274 * For a DFS path the function parse_dfs_path()
275 * will do the path processing, just make a copy.
281 if (lp_posix_pathnames()) {
282 *err = check_path_syntax_posix(*pp_dest);
284 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
290 /****************************************************************************
291 Pull a string and check the path - provide for error return.
292 ****************************************************************************/
294 size_t srvstr_get_path(TALLOC_CTX *ctx,
295 const char *base_ptr,
304 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
305 src_len, flags, err, &ignore);
308 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
309 char **pp_dest, const char *src, int flags,
310 NTSTATUS *err, bool *contains_wcard)
312 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
313 pp_dest, src, smbreq_bufrem(req, src),
314 flags, err, contains_wcard);
317 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
318 char **pp_dest, const char *src, int flags,
322 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
323 flags, err, &ignore);
326 /****************************************************************************
327 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
328 ****************************************************************************/
330 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
333 if ((fsp == NULL) || (conn == NULL)) {
334 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
337 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
338 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
344 /****************************************************************************
345 Check if we have a correct fsp pointing to a file.
346 ****************************************************************************/
348 bool check_fsp(connection_struct *conn, struct smb_request *req,
351 if (!check_fsp_open(conn, req, fsp)) {
354 if (fsp->is_directory) {
355 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
358 if (fsp->fh->fd == -1) {
359 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
362 fsp->num_smb_operations++;
366 /****************************************************************************
367 Check if we have a correct fsp pointing to a quota fake file. Replacement for
368 the CHECK_NTQUOTA_HANDLE_OK macro.
369 ****************************************************************************/
371 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
374 if (!check_fsp_open(conn, req, fsp)) {
378 if (fsp->is_directory) {
382 if (fsp->fake_file_handle == NULL) {
386 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
390 if (fsp->fake_file_handle->private_data == NULL) {
397 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
398 const char *name, int name_type)
401 char *trim_name_type;
402 const char *retarget_parm;
405 int retarget_type = 0x20;
406 int retarget_port = 139;
407 struct sockaddr_storage retarget_addr;
408 struct sockaddr_in *in_addr;
412 if (get_socket_port(sconn->sock) != 139) {
416 trim_name = talloc_strdup(talloc_tos(), name);
417 if (trim_name == NULL) {
420 trim_char(trim_name, ' ', ' ');
422 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
424 if (trim_name_type == NULL) {
428 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
429 trim_name_type, NULL);
430 if (retarget_parm == NULL) {
431 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
434 if (retarget_parm == NULL) {
438 retarget = talloc_strdup(trim_name, retarget_parm);
439 if (retarget == NULL) {
443 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
445 p = strchr(retarget, ':');
448 retarget_port = atoi(p);
451 p = strchr_m(retarget, '#');
454 sscanf(p, "%x", &retarget_type);
457 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
459 DEBUG(10, ("could not resolve %s\n", retarget));
463 if (retarget_addr.ss_family != AF_INET) {
464 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
468 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
470 _smb_setlen(outbuf, 6);
471 SCVAL(outbuf, 0, 0x84);
472 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
473 *(uint16_t *)(outbuf+8) = htons(retarget_port);
475 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
477 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
483 TALLOC_FREE(trim_name);
487 /****************************************************************************
488 Reply to a (netbios-level) special message.
489 ****************************************************************************/
491 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
493 int msg_type = CVAL(inbuf,0);
494 int msg_flags = CVAL(inbuf,1);
496 * We only really use 4 bytes of the outbuf, but for the smb_setlen
497 * calculation & friends (srv_send_smb uses that) we need the full smb
500 char outbuf[smb_size];
502 memset(outbuf, '\0', sizeof(outbuf));
504 smb_setlen(outbuf,0);
507 case 0x81: /* session request */
509 /* inbuf_size is guarenteed to be at least 4. */
511 int name_type1, name_type2;
512 int name_len1, name_len2;
516 if (sconn->nbt.got_session) {
517 exit_server_cleanly("multiple session request not permitted");
520 SCVAL(outbuf,0,0x82);
523 /* inbuf_size is guaranteed to be at least 4. */
524 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
525 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
526 DEBUG(0,("Invalid name length in session request\n"));
529 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
530 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
531 DEBUG(0,("Invalid name length in session request\n"));
535 name_type1 = name_extract((unsigned char *)inbuf,
536 inbuf_size,(unsigned int)4,name1);
537 name_type2 = name_extract((unsigned char *)inbuf,
538 inbuf_size,(unsigned int)(4 + name_len1),name2);
540 if (name_type1 == -1 || name_type2 == -1) {
541 DEBUG(0,("Invalid name type in session request\n"));
545 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
546 name1, name_type1, name2, name_type2));
548 if (netbios_session_retarget(sconn, name1, name_type1)) {
549 exit_server_cleanly("retargeted client");
553 * Windows NT/2k uses "*SMBSERVER" and XP uses
554 * "*SMBSERV" arrggg!!!
556 if (strequal(name1, "*SMBSERVER ")
557 || strequal(name1, "*SMBSERV ")) {
558 fstrcpy(name1, sconn->client_id.addr);
561 set_local_machine_name(name1, True);
562 set_remote_machine_name(name2, True);
564 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
565 get_local_machine_name(), get_remote_machine_name(),
568 if (name_type2 == 'R') {
569 /* We are being asked for a pathworks session ---
571 SCVAL(outbuf, 0,0x83);
575 /* only add the client's machine name to the list
576 of possibly valid usernames if we are operating
577 in share mode security */
578 if (lp_security() == SEC_SHARE) {
579 add_session_user(sconn, get_remote_machine_name());
582 reload_services(sconn->msg_ctx, sconn->sock, True);
585 sconn->nbt.got_session = true;
589 case 0x89: /* session keepalive request
590 (some old clients produce this?) */
591 SCVAL(outbuf,0,SMBkeepalive);
595 case 0x82: /* positive session response */
596 case 0x83: /* negative session response */
597 case 0x84: /* retarget session response */
598 DEBUG(0,("Unexpected session response\n"));
601 case SMBkeepalive: /* session keepalive */
606 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
607 msg_type, msg_flags));
609 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
613 /****************************************************************************
615 conn POINTER CAN BE NULL HERE !
616 ****************************************************************************/
618 void reply_tcon(struct smb_request *req)
620 connection_struct *conn = req->conn;
622 char *service_buf = NULL;
623 char *password = NULL;
628 DATA_BLOB password_blob;
629 TALLOC_CTX *ctx = talloc_tos();
630 struct smbd_server_connection *sconn = req->sconn;
632 START_PROFILE(SMBtcon);
634 if (req->buflen < 4) {
635 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
636 END_PROFILE(SMBtcon);
640 p = (const char *)req->buf + 1;
641 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
643 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
645 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
648 if (service_buf == NULL || password == NULL || dev == NULL) {
649 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
650 END_PROFILE(SMBtcon);
653 p = strrchr_m(service_buf,'\\');
657 service = service_buf;
660 password_blob = data_blob(password, pwlen+1);
662 conn = make_connection(sconn,service,password_blob,dev,
663 req->vuid,&nt_status);
666 data_blob_clear_free(&password_blob);
669 reply_nterror(req, nt_status);
670 END_PROFILE(SMBtcon);
674 reply_outbuf(req, 2, 0);
675 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
676 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
677 SSVAL(req->outbuf,smb_tid,conn->cnum);
679 DEBUG(3,("tcon service=%s cnum=%d\n",
680 service, conn->cnum));
682 END_PROFILE(SMBtcon);
686 /****************************************************************************
687 Reply to a tcon and X.
688 conn POINTER CAN BE NULL HERE !
689 ****************************************************************************/
691 void reply_tcon_and_X(struct smb_request *req)
693 connection_struct *conn = req->conn;
694 const char *service = NULL;
696 TALLOC_CTX *ctx = talloc_tos();
697 /* what the cleint thinks the device is */
698 char *client_devicetype = NULL;
699 /* what the server tells the client the share represents */
700 const char *server_devicetype;
706 struct smbd_server_connection *sconn = req->sconn;
708 START_PROFILE(SMBtconX);
711 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
712 END_PROFILE(SMBtconX);
716 passlen = SVAL(req->vwv+3, 0);
717 tcon_flags = SVAL(req->vwv+2, 0);
719 /* we might have to close an old one */
720 if ((tcon_flags & 0x1) && conn) {
721 close_cnum(conn,req->vuid);
726 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
727 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
728 END_PROFILE(SMBtconX);
732 if (sconn->smb1.negprot.encrypted_passwords) {
733 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
734 if (lp_security() == SEC_SHARE) {
736 * Security = share always has a pad byte
737 * after the password.
739 p = (const char *)req->buf + passlen + 1;
741 p = (const char *)req->buf + passlen;
744 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
745 /* Ensure correct termination */
746 password.data[passlen]=0;
747 p = (const char *)req->buf + passlen + 1;
750 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
753 data_blob_clear_free(&password);
754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
755 END_PROFILE(SMBtconX);
760 * the service name can be either: \\server\share
761 * or share directly like on the DELL PowerVault 705
764 q = strchr_m(path+2,'\\');
766 data_blob_clear_free(&password);
767 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
768 END_PROFILE(SMBtconX);
776 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
777 &client_devicetype, p,
778 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
780 if (client_devicetype == NULL) {
781 data_blob_clear_free(&password);
782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
783 END_PROFILE(SMBtconX);
787 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
789 conn = make_connection(sconn, service, password, client_devicetype,
790 req->vuid, &nt_status);
793 data_blob_clear_free(&password);
796 reply_nterror(req, nt_status);
797 END_PROFILE(SMBtconX);
802 server_devicetype = "IPC";
803 else if ( IS_PRINT(conn) )
804 server_devicetype = "LPT1:";
806 server_devicetype = "A:";
808 if (get_Protocol() < PROTOCOL_NT1) {
809 reply_outbuf(req, 2, 0);
810 if (message_push_string(&req->outbuf, server_devicetype,
811 STR_TERMINATE|STR_ASCII) == -1) {
812 reply_nterror(req, NT_STATUS_NO_MEMORY);
813 END_PROFILE(SMBtconX);
817 /* NT sets the fstype of IPC$ to the null string */
818 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
820 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
821 /* Return permissions. */
825 reply_outbuf(req, 7, 0);
828 perm1 = FILE_ALL_ACCESS;
829 perm2 = FILE_ALL_ACCESS;
831 perm1 = CAN_WRITE(conn) ?
836 SIVAL(req->outbuf, smb_vwv3, perm1);
837 SIVAL(req->outbuf, smb_vwv5, perm2);
839 reply_outbuf(req, 3, 0);
842 if ((message_push_string(&req->outbuf, server_devicetype,
843 STR_TERMINATE|STR_ASCII) == -1)
844 || (message_push_string(&req->outbuf, fstype,
845 STR_TERMINATE) == -1)) {
846 reply_nterror(req, NT_STATUS_NO_MEMORY);
847 END_PROFILE(SMBtconX);
851 /* what does setting this bit do? It is set by NT4 and
852 may affect the ability to autorun mounted cdroms */
853 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
854 (lp_csc_policy(SNUM(conn)) << 2));
856 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
857 DEBUG(2,("Serving %s as a Dfs root\n",
858 lp_servicename(SNUM(conn)) ));
859 SSVAL(req->outbuf, smb_vwv2,
860 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
865 DEBUG(3,("tconX service=%s \n",
868 /* set the incoming and outgoing tid to the just created one */
869 SSVAL(req->inbuf,smb_tid,conn->cnum);
870 SSVAL(req->outbuf,smb_tid,conn->cnum);
872 END_PROFILE(SMBtconX);
874 req->tid = conn->cnum;
879 /****************************************************************************
880 Reply to an unknown type.
881 ****************************************************************************/
883 void reply_unknown_new(struct smb_request *req, uint8 type)
885 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
886 smb_fn_name(type), type, type));
887 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
891 /****************************************************************************
893 conn POINTER CAN BE NULL HERE !
894 ****************************************************************************/
896 void reply_ioctl(struct smb_request *req)
898 connection_struct *conn = req->conn;
905 START_PROFILE(SMBioctl);
908 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
909 END_PROFILE(SMBioctl);
913 device = SVAL(req->vwv+1, 0);
914 function = SVAL(req->vwv+2, 0);
915 ioctl_code = (device << 16) + function;
917 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
919 switch (ioctl_code) {
920 case IOCTL_QUERY_JOB_INFO:
924 reply_force_doserror(req, ERRSRV, ERRnosupport);
925 END_PROFILE(SMBioctl);
929 reply_outbuf(req, 8, replysize+1);
930 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
931 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
932 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
933 p = smb_buf(req->outbuf);
934 memset(p, '\0', replysize+1); /* valgrind-safe. */
935 p += 1; /* Allow for alignment */
937 switch (ioctl_code) {
938 case IOCTL_QUERY_JOB_INFO:
940 files_struct *fsp = file_fsp(
941 req, SVAL(req->vwv+0, 0));
943 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
944 END_PROFILE(SMBioctl);
948 if (fsp->print_file) {
949 SSVAL(p, 0, fsp->print_file->rap_jobid);
953 srvstr_push((char *)req->outbuf, req->flags2, p+2,
955 STR_TERMINATE|STR_ASCII);
957 srvstr_push((char *)req->outbuf, req->flags2,
958 p+18, lp_servicename(SNUM(conn)),
959 13, STR_TERMINATE|STR_ASCII);
967 END_PROFILE(SMBioctl);
971 /****************************************************************************
972 Strange checkpath NTSTATUS mapping.
973 ****************************************************************************/
975 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
977 /* Strange DOS error code semantics only for checkpath... */
978 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
979 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
980 /* We need to map to ERRbadpath */
981 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
987 /****************************************************************************
988 Reply to a checkpath.
989 ****************************************************************************/
991 void reply_checkpath(struct smb_request *req)
993 connection_struct *conn = req->conn;
994 struct smb_filename *smb_fname = NULL;
997 TALLOC_CTX *ctx = talloc_tos();
999 START_PROFILE(SMBcheckpath);
1001 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1002 STR_TERMINATE, &status);
1004 if (!NT_STATUS_IS_OK(status)) {
1005 status = map_checkpath_error(req->flags2, status);
1006 reply_nterror(req, status);
1007 END_PROFILE(SMBcheckpath);
1011 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1013 status = filename_convert(ctx,
1015 req->flags2 & FLAGS2_DFS_PATHNAMES,
1021 if (!NT_STATUS_IS_OK(status)) {
1022 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1023 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1024 ERRSRV, ERRbadpath);
1025 END_PROFILE(SMBcheckpath);
1031 if (!VALID_STAT(smb_fname->st) &&
1032 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1033 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1034 smb_fname_str_dbg(smb_fname), strerror(errno)));
1035 status = map_nt_error_from_unix(errno);
1039 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1040 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1041 ERRDOS, ERRbadpath);
1045 reply_outbuf(req, 0, 0);
1048 /* We special case this - as when a Windows machine
1049 is parsing a path is steps through the components
1050 one at a time - if a component fails it expects
1051 ERRbadpath, not ERRbadfile.
1053 status = map_checkpath_error(req->flags2, status);
1054 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1056 * Windows returns different error codes if
1057 * the parent directory is valid but not the
1058 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1059 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1060 * if the path is invalid.
1062 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1063 ERRDOS, ERRbadpath);
1067 reply_nterror(req, status);
1070 TALLOC_FREE(smb_fname);
1071 END_PROFILE(SMBcheckpath);
1075 /****************************************************************************
1077 ****************************************************************************/
1079 void reply_getatr(struct smb_request *req)
1081 connection_struct *conn = req->conn;
1082 struct smb_filename *smb_fname = NULL;
1089 TALLOC_CTX *ctx = talloc_tos();
1090 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1092 START_PROFILE(SMBgetatr);
1094 p = (const char *)req->buf + 1;
1095 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1096 if (!NT_STATUS_IS_OK(status)) {
1097 reply_nterror(req, status);
1101 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1102 under WfWg - weird! */
1103 if (*fname == '\0') {
1104 mode = aHIDDEN | aDIR;
1105 if (!CAN_WRITE(conn)) {
1111 status = filename_convert(ctx,
1113 req->flags2 & FLAGS2_DFS_PATHNAMES,
1118 if (!NT_STATUS_IS_OK(status)) {
1119 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1120 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1121 ERRSRV, ERRbadpath);
1124 reply_nterror(req, status);
1127 if (!VALID_STAT(smb_fname->st) &&
1128 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1129 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1130 smb_fname_str_dbg(smb_fname),
1132 reply_nterror(req, map_nt_error_from_unix(errno));
1136 mode = dos_mode(conn, smb_fname);
1137 size = smb_fname->st.st_ex_size;
1139 if (ask_sharemode) {
1140 struct timespec write_time_ts;
1141 struct file_id fileid;
1143 ZERO_STRUCT(write_time_ts);
1144 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1145 get_file_infos(fileid, 0, NULL, &write_time_ts);
1146 if (!null_timespec(write_time_ts)) {
1147 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1151 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1157 reply_outbuf(req, 10, 0);
1159 SSVAL(req->outbuf,smb_vwv0,mode);
1160 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1161 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1163 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1165 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1167 if (get_Protocol() >= PROTOCOL_NT1) {
1168 SSVAL(req->outbuf, smb_flg2,
1169 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1172 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1173 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1176 TALLOC_FREE(smb_fname);
1178 END_PROFILE(SMBgetatr);
1182 /****************************************************************************
1184 ****************************************************************************/
1186 void reply_setatr(struct smb_request *req)
1188 struct smb_file_time ft;
1189 connection_struct *conn = req->conn;
1190 struct smb_filename *smb_fname = NULL;
1196 TALLOC_CTX *ctx = talloc_tos();
1198 START_PROFILE(SMBsetatr);
1203 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1207 p = (const char *)req->buf + 1;
1208 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1209 if (!NT_STATUS_IS_OK(status)) {
1210 reply_nterror(req, status);
1214 status = filename_convert(ctx,
1216 req->flags2 & FLAGS2_DFS_PATHNAMES,
1221 if (!NT_STATUS_IS_OK(status)) {
1222 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1223 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1224 ERRSRV, ERRbadpath);
1227 reply_nterror(req, status);
1231 if (smb_fname->base_name[0] == '.' &&
1232 smb_fname->base_name[1] == '\0') {
1234 * Not sure here is the right place to catch this
1235 * condition. Might be moved to somewhere else later -- vl
1237 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1241 mode = SVAL(req->vwv+0, 0);
1242 mtime = srv_make_unix_date3(req->vwv+1);
1244 ft.mtime = convert_time_t_to_timespec(mtime);
1245 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1246 if (!NT_STATUS_IS_OK(status)) {
1247 reply_nterror(req, status);
1251 if (mode != FILE_ATTRIBUTE_NORMAL) {
1252 if (VALID_STAT_OF_DIR(smb_fname->st))
1257 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1259 reply_nterror(req, map_nt_error_from_unix(errno));
1264 reply_outbuf(req, 0, 0);
1266 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1269 TALLOC_FREE(smb_fname);
1270 END_PROFILE(SMBsetatr);
1274 /****************************************************************************
1276 ****************************************************************************/
1278 void reply_dskattr(struct smb_request *req)
1280 connection_struct *conn = req->conn;
1281 uint64_t dfree,dsize,bsize;
1282 START_PROFILE(SMBdskattr);
1284 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1285 reply_nterror(req, map_nt_error_from_unix(errno));
1286 END_PROFILE(SMBdskattr);
1290 reply_outbuf(req, 5, 0);
1292 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1293 double total_space, free_space;
1294 /* we need to scale this to a number that DOS6 can handle. We
1295 use floating point so we can handle large drives on systems
1296 that don't have 64 bit integers
1298 we end up displaying a maximum of 2G to DOS systems
1300 total_space = dsize * (double)bsize;
1301 free_space = dfree * (double)bsize;
1303 dsize = (uint64_t)((total_space+63*512) / (64*512));
1304 dfree = (uint64_t)((free_space+63*512) / (64*512));
1306 if (dsize > 0xFFFF) dsize = 0xFFFF;
1307 if (dfree > 0xFFFF) dfree = 0xFFFF;
1309 SSVAL(req->outbuf,smb_vwv0,dsize);
1310 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1311 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1312 SSVAL(req->outbuf,smb_vwv3,dfree);
1314 SSVAL(req->outbuf,smb_vwv0,dsize);
1315 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1316 SSVAL(req->outbuf,smb_vwv2,512);
1317 SSVAL(req->outbuf,smb_vwv3,dfree);
1320 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1322 END_PROFILE(SMBdskattr);
1327 * Utility function to split the filename from the directory.
1329 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1330 char **fname_dir_out,
1331 char **fname_mask_out)
1333 const char *p = NULL;
1334 char *fname_dir = NULL;
1335 char *fname_mask = NULL;
1337 p = strrchr_m(fname_in, '/');
1339 fname_dir = talloc_strdup(ctx, ".");
1340 fname_mask = talloc_strdup(ctx, fname_in);
1342 fname_dir = talloc_strndup(ctx, fname_in,
1343 PTR_DIFF(p, fname_in));
1344 fname_mask = talloc_strdup(ctx, p+1);
1347 if (!fname_dir || !fname_mask) {
1348 TALLOC_FREE(fname_dir);
1349 TALLOC_FREE(fname_mask);
1350 return NT_STATUS_NO_MEMORY;
1353 *fname_dir_out = fname_dir;
1354 *fname_mask_out = fname_mask;
1355 return NT_STATUS_OK;
1358 /****************************************************************************
1360 Can be called from SMBsearch, SMBffirst or SMBfunique.
1361 ****************************************************************************/
1363 void reply_search(struct smb_request *req)
1365 connection_struct *conn = req->conn;
1367 const char *mask = NULL;
1368 char *directory = NULL;
1369 struct smb_filename *smb_fname = NULL;
1373 struct timespec date;
1375 unsigned int numentries = 0;
1376 unsigned int maxentries = 0;
1377 bool finished = False;
1382 bool check_descend = False;
1383 bool expect_close = False;
1385 bool mask_contains_wcard = False;
1386 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1387 TALLOC_CTX *ctx = talloc_tos();
1388 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1389 struct dptr_struct *dirptr = NULL;
1390 struct smbd_server_connection *sconn = req->sconn;
1392 START_PROFILE(SMBsearch);
1395 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1399 if (lp_posix_pathnames()) {
1400 reply_unknown_new(req, req->cmd);
1404 /* If we were called as SMBffirst then we must expect close. */
1405 if(req->cmd == SMBffirst) {
1406 expect_close = True;
1409 reply_outbuf(req, 1, 3);
1410 maxentries = SVAL(req->vwv+0, 0);
1411 dirtype = SVAL(req->vwv+1, 0);
1412 p = (const char *)req->buf + 1;
1413 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1414 &nt_status, &mask_contains_wcard);
1415 if (!NT_STATUS_IS_OK(nt_status)) {
1416 reply_nterror(req, nt_status);
1421 status_len = SVAL(p, 0);
1424 /* dirtype &= ~aDIR; */
1426 if (status_len == 0) {
1427 nt_status = filename_convert(ctx, conn,
1428 req->flags2 & FLAGS2_DFS_PATHNAMES,
1430 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1431 &mask_contains_wcard,
1433 if (!NT_STATUS_IS_OK(nt_status)) {
1434 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1435 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1436 ERRSRV, ERRbadpath);
1439 reply_nterror(req, nt_status);
1443 directory = smb_fname->base_name;
1445 p = strrchr_m(directory,'/');
1446 if ((p != NULL) && (*directory != '/')) {
1448 directory = talloc_strndup(ctx, directory,
1449 PTR_DIFF(p, directory));
1452 directory = talloc_strdup(ctx,".");
1456 reply_nterror(req, NT_STATUS_NO_MEMORY);
1460 memset((char *)status,'\0',21);
1461 SCVAL(status,0,(dirtype & 0x1F));
1463 nt_status = dptr_create(conn,
1470 mask_contains_wcard,
1473 if (!NT_STATUS_IS_OK(nt_status)) {
1474 reply_nterror(req, nt_status);
1477 dptr_num = dptr_dnum(dirptr);
1480 const char *dirpath;
1482 memcpy(status,p,21);
1483 status_dirtype = CVAL(status,0) & 0x1F;
1484 if (status_dirtype != (dirtype & 0x1F)) {
1485 dirtype = status_dirtype;
1488 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1492 dirpath = dptr_path(sconn, dptr_num);
1493 directory = talloc_strdup(ctx, dirpath);
1495 reply_nterror(req, NT_STATUS_NO_MEMORY);
1499 mask = dptr_wcard(sconn, dptr_num);
1504 * For a 'continue' search we have no string. So
1505 * check from the initial saved string.
1507 mask_contains_wcard = ms_has_wild(mask);
1508 dirtype = dptr_attr(sconn, dptr_num);
1511 DEBUG(4,("dptr_num is %d\n",dptr_num));
1513 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1514 dptr_init_search_op(dirptr);
1516 if ((dirtype&0x1F) == aVOLID) {
1517 char buf[DIR_STRUCT_SIZE];
1518 memcpy(buf,status,21);
1519 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1520 0,aVOLID,0,!allow_long_path_components)) {
1521 reply_nterror(req, NT_STATUS_NO_MEMORY);
1524 dptr_fill(sconn, buf+12,dptr_num);
1525 if (dptr_zero(buf+12) && (status_len==0)) {
1530 if (message_push_blob(&req->outbuf,
1531 data_blob_const(buf, sizeof(buf)))
1533 reply_nterror(req, NT_STATUS_NO_MEMORY);
1541 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1544 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1545 directory,lp_dontdescend(SNUM(conn))));
1546 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1547 check_descend = True;
1550 for (i=numentries;(i<maxentries) && !finished;i++) {
1551 finished = !get_dir_entry(ctx,
1562 char buf[DIR_STRUCT_SIZE];
1563 memcpy(buf,status,21);
1564 if (!make_dir_struct(ctx,
1570 convert_timespec_to_time_t(date),
1571 !allow_long_path_components)) {
1572 reply_nterror(req, NT_STATUS_NO_MEMORY);
1575 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1578 if (message_push_blob(&req->outbuf,
1579 data_blob_const(buf, sizeof(buf)))
1581 reply_nterror(req, NT_STATUS_NO_MEMORY);
1591 /* If we were called as SMBffirst with smb_search_id == NULL
1592 and no entries were found then return error and close dirptr
1595 if (numentries == 0) {
1596 dptr_close(sconn, &dptr_num);
1597 } else if(expect_close && status_len == 0) {
1598 /* Close the dptr - we know it's gone */
1599 dptr_close(sconn, &dptr_num);
1602 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1603 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1604 dptr_close(sconn, &dptr_num);
1607 if ((numentries == 0) && !mask_contains_wcard) {
1608 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1612 SSVAL(req->outbuf,smb_vwv0,numentries);
1613 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1614 SCVAL(smb_buf(req->outbuf),0,5);
1615 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1617 /* The replies here are never long name. */
1618 SSVAL(req->outbuf, smb_flg2,
1619 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1620 if (!allow_long_path_components) {
1621 SSVAL(req->outbuf, smb_flg2,
1622 SVAL(req->outbuf, smb_flg2)
1623 & (~FLAGS2_LONG_PATH_COMPONENTS));
1626 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1627 SSVAL(req->outbuf, smb_flg2,
1628 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1630 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1631 smb_fn_name(req->cmd),
1638 TALLOC_FREE(directory);
1639 TALLOC_FREE(smb_fname);
1640 END_PROFILE(SMBsearch);
1644 /****************************************************************************
1645 Reply to a fclose (stop directory search).
1646 ****************************************************************************/
1648 void reply_fclose(struct smb_request *req)
1656 bool path_contains_wcard = False;
1657 TALLOC_CTX *ctx = talloc_tos();
1658 struct smbd_server_connection *sconn = req->sconn;
1660 START_PROFILE(SMBfclose);
1662 if (lp_posix_pathnames()) {
1663 reply_unknown_new(req, req->cmd);
1664 END_PROFILE(SMBfclose);
1668 p = (const char *)req->buf + 1;
1669 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1670 &err, &path_contains_wcard);
1671 if (!NT_STATUS_IS_OK(err)) {
1672 reply_nterror(req, err);
1673 END_PROFILE(SMBfclose);
1677 status_len = SVAL(p,0);
1680 if (status_len == 0) {
1681 reply_force_doserror(req, ERRSRV, ERRsrverror);
1682 END_PROFILE(SMBfclose);
1686 memcpy(status,p,21);
1688 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1689 /* Close the dptr - we know it's gone */
1690 dptr_close(sconn, &dptr_num);
1693 reply_outbuf(req, 1, 0);
1694 SSVAL(req->outbuf,smb_vwv0,0);
1696 DEBUG(3,("search close\n"));
1698 END_PROFILE(SMBfclose);
1702 /****************************************************************************
1704 ****************************************************************************/
1706 void reply_open(struct smb_request *req)
1708 connection_struct *conn = req->conn;
1709 struct smb_filename *smb_fname = NULL;
1721 uint32 create_disposition;
1722 uint32 create_options = 0;
1723 uint32_t private_flags = 0;
1725 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1726 TALLOC_CTX *ctx = talloc_tos();
1728 START_PROFILE(SMBopen);
1731 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1735 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1736 deny_mode = SVAL(req->vwv+0, 0);
1737 dos_attr = SVAL(req->vwv+1, 0);
1739 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1740 STR_TERMINATE, &status);
1741 if (!NT_STATUS_IS_OK(status)) {
1742 reply_nterror(req, status);
1746 status = filename_convert(ctx,
1748 req->flags2 & FLAGS2_DFS_PATHNAMES,
1753 if (!NT_STATUS_IS_OK(status)) {
1754 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1755 reply_botherror(req,
1756 NT_STATUS_PATH_NOT_COVERED,
1757 ERRSRV, ERRbadpath);
1760 reply_nterror(req, status);
1764 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1765 OPENX_FILE_EXISTS_OPEN, &access_mask,
1766 &share_mode, &create_disposition,
1767 &create_options, &private_flags)) {
1768 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1772 status = SMB_VFS_CREATE_FILE(
1775 0, /* root_dir_fid */
1776 smb_fname, /* fname */
1777 access_mask, /* access_mask */
1778 share_mode, /* share_access */
1779 create_disposition, /* create_disposition*/
1780 create_options, /* create_options */
1781 dos_attr, /* file_attributes */
1782 oplock_request, /* oplock_request */
1783 0, /* allocation_size */
1790 if (!NT_STATUS_IS_OK(status)) {
1791 if (open_was_deferred(req->mid)) {
1792 /* We have re-scheduled this call. */
1795 reply_openerror(req, status);
1799 size = smb_fname->st.st_ex_size;
1800 fattr = dos_mode(conn, smb_fname);
1802 /* Deal with other possible opens having a modified
1804 if (ask_sharemode) {
1805 struct timespec write_time_ts;
1807 ZERO_STRUCT(write_time_ts);
1808 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1809 if (!null_timespec(write_time_ts)) {
1810 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1814 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1817 DEBUG(3,("attempt to open a directory %s\n",
1819 close_file(req, fsp, ERROR_CLOSE);
1820 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1821 ERRDOS, ERRnoaccess);
1825 reply_outbuf(req, 7, 0);
1826 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1827 SSVAL(req->outbuf,smb_vwv1,fattr);
1828 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1829 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1831 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1833 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1834 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1836 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1837 SCVAL(req->outbuf,smb_flg,
1838 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1841 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1842 SCVAL(req->outbuf,smb_flg,
1843 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1846 TALLOC_FREE(smb_fname);
1847 END_PROFILE(SMBopen);
1851 /****************************************************************************
1852 Reply to an open and X.
1853 ****************************************************************************/
1855 void reply_open_and_X(struct smb_request *req)
1857 connection_struct *conn = req->conn;
1858 struct smb_filename *smb_fname = NULL;
1863 /* Breakout the oplock request bits so we can set the
1864 reply bits separately. */
1865 int ex_oplock_request;
1866 int core_oplock_request;
1869 int smb_sattr = SVAL(req->vwv+4, 0);
1870 uint32 smb_time = make_unix_date3(req->vwv+6);
1878 uint64_t allocation_size;
1879 ssize_t retval = -1;
1882 uint32 create_disposition;
1883 uint32 create_options = 0;
1884 uint32_t private_flags = 0;
1885 TALLOC_CTX *ctx = talloc_tos();
1887 START_PROFILE(SMBopenX);
1889 if (req->wct < 15) {
1890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1894 open_flags = SVAL(req->vwv+2, 0);
1895 deny_mode = SVAL(req->vwv+3, 0);
1896 smb_attr = SVAL(req->vwv+5, 0);
1897 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1898 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1899 oplock_request = ex_oplock_request | core_oplock_request;
1900 smb_ofun = SVAL(req->vwv+8, 0);
1901 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1903 /* If it's an IPC, pass off the pipe handler. */
1905 if (lp_nt_pipe_support()) {
1906 reply_open_pipe_and_X(conn, req);
1908 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1913 /* XXXX we need to handle passed times, sattr and flags */
1914 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1915 STR_TERMINATE, &status);
1916 if (!NT_STATUS_IS_OK(status)) {
1917 reply_nterror(req, status);
1921 status = filename_convert(ctx,
1923 req->flags2 & FLAGS2_DFS_PATHNAMES,
1928 if (!NT_STATUS_IS_OK(status)) {
1929 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1930 reply_botherror(req,
1931 NT_STATUS_PATH_NOT_COVERED,
1932 ERRSRV, ERRbadpath);
1935 reply_nterror(req, status);
1939 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1940 &access_mask, &share_mode,
1941 &create_disposition,
1944 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1948 status = SMB_VFS_CREATE_FILE(
1951 0, /* root_dir_fid */
1952 smb_fname, /* fname */
1953 access_mask, /* access_mask */
1954 share_mode, /* share_access */
1955 create_disposition, /* create_disposition*/
1956 create_options, /* create_options */
1957 smb_attr, /* file_attributes */
1958 oplock_request, /* oplock_request */
1959 0, /* allocation_size */
1964 &smb_action); /* pinfo */
1966 if (!NT_STATUS_IS_OK(status)) {
1967 if (open_was_deferred(req->mid)) {
1968 /* We have re-scheduled this call. */
1971 reply_openerror(req, status);
1975 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1976 if the file is truncated or created. */
1977 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1978 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1979 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1980 close_file(req, fsp, ERROR_CLOSE);
1981 reply_nterror(req, NT_STATUS_DISK_FULL);
1984 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1986 close_file(req, fsp, ERROR_CLOSE);
1987 reply_nterror(req, NT_STATUS_DISK_FULL);
1990 status = vfs_stat_fsp(fsp);
1991 if (!NT_STATUS_IS_OK(status)) {
1992 close_file(req, fsp, ERROR_CLOSE);
1993 reply_nterror(req, status);
1998 fattr = dos_mode(conn, fsp->fsp_name);
1999 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2001 close_file(req, fsp, ERROR_CLOSE);
2002 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2006 /* If the caller set the extended oplock request bit
2007 and we granted one (by whatever means) - set the
2008 correct bit for extended oplock reply.
2011 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2012 smb_action |= EXTENDED_OPLOCK_GRANTED;
2015 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2016 smb_action |= EXTENDED_OPLOCK_GRANTED;
2019 /* If the caller set the core oplock request bit
2020 and we granted one (by whatever means) - set the
2021 correct bit for core oplock reply.
2024 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2025 reply_outbuf(req, 19, 0);
2027 reply_outbuf(req, 15, 0);
2030 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2031 SCVAL(req->outbuf, smb_flg,
2032 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2035 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2036 SCVAL(req->outbuf, smb_flg,
2037 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2040 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2041 SSVAL(req->outbuf,smb_vwv3,fattr);
2042 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2043 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2045 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2047 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2048 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2049 SSVAL(req->outbuf,smb_vwv11,smb_action);
2051 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2052 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2057 TALLOC_FREE(smb_fname);
2058 END_PROFILE(SMBopenX);
2062 /****************************************************************************
2063 Reply to a SMBulogoffX.
2064 ****************************************************************************/
2066 void reply_ulogoffX(struct smb_request *req)
2068 struct smbd_server_connection *sconn = req->sconn;
2071 START_PROFILE(SMBulogoffX);
2073 vuser = get_valid_user_struct(sconn, req->vuid);
2076 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2080 /* in user level security we are supposed to close any files
2081 open by this user */
2082 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2083 file_close_user(sconn, req->vuid);
2086 invalidate_vuid(sconn, req->vuid);
2088 reply_outbuf(req, 2, 0);
2090 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2092 END_PROFILE(SMBulogoffX);
2093 req->vuid = UID_FIELD_INVALID;
2097 /****************************************************************************
2098 Reply to a mknew or a create.
2099 ****************************************************************************/
2101 void reply_mknew(struct smb_request *req)
2103 connection_struct *conn = req->conn;
2104 struct smb_filename *smb_fname = NULL;
2107 struct smb_file_time ft;
2109 int oplock_request = 0;
2111 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2112 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2113 uint32 create_disposition;
2114 uint32 create_options = 0;
2115 TALLOC_CTX *ctx = talloc_tos();
2117 START_PROFILE(SMBcreate);
2121 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2125 fattr = SVAL(req->vwv+0, 0);
2126 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2129 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2131 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2132 STR_TERMINATE, &status);
2133 if (!NT_STATUS_IS_OK(status)) {
2134 reply_nterror(req, status);
2138 status = filename_convert(ctx,
2140 req->flags2 & FLAGS2_DFS_PATHNAMES,
2145 if (!NT_STATUS_IS_OK(status)) {
2146 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2147 reply_botherror(req,
2148 NT_STATUS_PATH_NOT_COVERED,
2149 ERRSRV, ERRbadpath);
2152 reply_nterror(req, status);
2156 if (fattr & aVOLID) {
2157 DEBUG(0,("Attempt to create file (%s) with volid set - "
2158 "please report this\n",
2159 smb_fname_str_dbg(smb_fname)));
2162 if(req->cmd == SMBmknew) {
2163 /* We should fail if file exists. */
2164 create_disposition = FILE_CREATE;
2166 /* Create if file doesn't exist, truncate if it does. */
2167 create_disposition = FILE_OVERWRITE_IF;
2170 status = SMB_VFS_CREATE_FILE(
2173 0, /* root_dir_fid */
2174 smb_fname, /* fname */
2175 access_mask, /* access_mask */
2176 share_mode, /* share_access */
2177 create_disposition, /* create_disposition*/
2178 create_options, /* create_options */
2179 fattr, /* file_attributes */
2180 oplock_request, /* oplock_request */
2181 0, /* allocation_size */
2182 0, /* private_flags */
2188 if (!NT_STATUS_IS_OK(status)) {
2189 if (open_was_deferred(req->mid)) {
2190 /* We have re-scheduled this call. */
2193 reply_openerror(req, status);
2197 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2198 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2199 if (!NT_STATUS_IS_OK(status)) {
2200 END_PROFILE(SMBcreate);
2204 reply_outbuf(req, 1, 0);
2205 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2207 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2208 SCVAL(req->outbuf,smb_flg,
2209 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2212 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2213 SCVAL(req->outbuf,smb_flg,
2214 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2217 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2218 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2219 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2220 (unsigned int)fattr));
2223 TALLOC_FREE(smb_fname);
2224 END_PROFILE(SMBcreate);
2228 /****************************************************************************
2229 Reply to a create temporary file.
2230 ****************************************************************************/
2232 void reply_ctemp(struct smb_request *req)
2234 connection_struct *conn = req->conn;
2235 struct smb_filename *smb_fname = NULL;
2243 TALLOC_CTX *ctx = talloc_tos();
2245 START_PROFILE(SMBctemp);
2248 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2252 fattr = SVAL(req->vwv+0, 0);
2253 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2255 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2256 STR_TERMINATE, &status);
2257 if (!NT_STATUS_IS_OK(status)) {
2258 reply_nterror(req, status);
2262 fname = talloc_asprintf(ctx,
2266 fname = talloc_strdup(ctx, "TMXXXXXX");
2270 reply_nterror(req, NT_STATUS_NO_MEMORY);
2274 status = filename_convert(ctx, conn,
2275 req->flags2 & FLAGS2_DFS_PATHNAMES,
2280 if (!NT_STATUS_IS_OK(status)) {
2281 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2282 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2283 ERRSRV, ERRbadpath);
2286 reply_nterror(req, status);
2290 tmpfd = mkstemp(smb_fname->base_name);
2292 reply_nterror(req, map_nt_error_from_unix(errno));
2296 SMB_VFS_STAT(conn, smb_fname);
2298 /* We should fail if file does not exist. */
2299 status = SMB_VFS_CREATE_FILE(
2302 0, /* root_dir_fid */
2303 smb_fname, /* fname */
2304 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2305 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2306 FILE_OPEN, /* create_disposition*/
2307 0, /* create_options */
2308 fattr, /* file_attributes */
2309 oplock_request, /* oplock_request */
2310 0, /* allocation_size */
2311 0, /* private_flags */
2317 /* close fd from mkstemp() */
2320 if (!NT_STATUS_IS_OK(status)) {
2321 if (open_was_deferred(req->mid)) {
2322 /* We have re-scheduled this call. */
2325 reply_openerror(req, status);
2329 reply_outbuf(req, 1, 0);
2330 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2332 /* the returned filename is relative to the directory */
2333 s = strrchr_m(fsp->fsp_name->base_name, '/');
2335 s = fsp->fsp_name->base_name;
2341 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2342 thing in the byte section. JRA */
2343 SSVALS(p, 0, -1); /* what is this? not in spec */
2345 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2347 reply_nterror(req, NT_STATUS_NO_MEMORY);
2351 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2352 SCVAL(req->outbuf, smb_flg,
2353 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2356 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2357 SCVAL(req->outbuf, smb_flg,
2358 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2361 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2362 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2363 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2365 TALLOC_FREE(smb_fname);
2366 END_PROFILE(SMBctemp);
2370 /*******************************************************************
2371 Check if a user is allowed to rename a file.
2372 ********************************************************************/
2374 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2379 if (!CAN_WRITE(conn)) {
2380 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2383 fmode = dos_mode(conn, fsp->fsp_name);
2384 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2385 return NT_STATUS_NO_SUCH_FILE;
2388 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2389 if (fsp->posix_open) {
2390 return NT_STATUS_OK;
2393 /* If no pathnames are open below this
2394 directory, allow the rename. */
2396 if (file_find_subpath(fsp)) {
2397 return NT_STATUS_ACCESS_DENIED;
2399 return NT_STATUS_OK;
2402 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2403 return NT_STATUS_OK;
2406 return NT_STATUS_ACCESS_DENIED;
2409 /*******************************************************************
2410 * unlink a file with all relevant access checks
2411 *******************************************************************/
2413 static NTSTATUS do_unlink(connection_struct *conn,
2414 struct smb_request *req,
2415 struct smb_filename *smb_fname,
2420 uint32 dirtype_orig = dirtype;
2423 bool posix_paths = lp_posix_pathnames();
2425 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2426 smb_fname_str_dbg(smb_fname),
2429 if (!CAN_WRITE(conn)) {
2430 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2434 ret = SMB_VFS_LSTAT(conn, smb_fname);
2436 ret = SMB_VFS_STAT(conn, smb_fname);
2439 return map_nt_error_from_unix(errno);
2442 fattr = dos_mode(conn, smb_fname);
2444 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2445 dirtype = aDIR|aARCH|aRONLY;
2448 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2450 return NT_STATUS_NO_SUCH_FILE;
2453 if (!dir_check_ftype(conn, fattr, dirtype)) {
2455 return NT_STATUS_FILE_IS_A_DIRECTORY;
2457 return NT_STATUS_NO_SUCH_FILE;
2460 if (dirtype_orig & 0x8000) {
2461 /* These will never be set for POSIX. */
2462 return NT_STATUS_NO_SUCH_FILE;
2466 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2467 return NT_STATUS_FILE_IS_A_DIRECTORY;
2470 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2471 return NT_STATUS_NO_SUCH_FILE;
2474 if (dirtype & 0xFF00) {
2475 /* These will never be set for POSIX. */
2476 return NT_STATUS_NO_SUCH_FILE;
2481 return NT_STATUS_NO_SUCH_FILE;
2484 /* Can't delete a directory. */
2486 return NT_STATUS_FILE_IS_A_DIRECTORY;
2491 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2492 return NT_STATUS_OBJECT_NAME_INVALID;
2493 #endif /* JRATEST */
2495 /* On open checks the open itself will check the share mode, so
2496 don't do it here as we'll get it wrong. */
2498 status = SMB_VFS_CREATE_FILE
2501 0, /* root_dir_fid */
2502 smb_fname, /* fname */
2503 DELETE_ACCESS, /* access_mask */
2504 FILE_SHARE_NONE, /* share_access */
2505 FILE_OPEN, /* create_disposition*/
2506 FILE_NON_DIRECTORY_FILE, /* create_options */
2507 /* file_attributes */
2508 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2509 FILE_ATTRIBUTE_NORMAL,
2510 0, /* oplock_request */
2511 0, /* allocation_size */
2512 0, /* private_flags */
2518 if (!NT_STATUS_IS_OK(status)) {
2519 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2520 nt_errstr(status)));
2524 status = can_set_delete_on_close(fsp, fattr);
2525 if (!NT_STATUS_IS_OK(status)) {
2526 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2528 smb_fname_str_dbg(smb_fname),
2529 nt_errstr(status)));
2530 close_file(req, fsp, NORMAL_CLOSE);
2534 /* The set is across all open files on this dev/inode pair. */
2535 if (!set_delete_on_close(fsp, True, &conn->session_info->utok)) {
2536 close_file(req, fsp, NORMAL_CLOSE);
2537 return NT_STATUS_ACCESS_DENIED;
2540 return close_file(req, fsp, NORMAL_CLOSE);
2543 /****************************************************************************
2544 The guts of the unlink command, split out so it may be called by the NT SMB
2546 ****************************************************************************/
2548 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2549 uint32 dirtype, struct smb_filename *smb_fname,
2552 char *fname_dir = NULL;
2553 char *fname_mask = NULL;
2555 NTSTATUS status = NT_STATUS_OK;
2556 TALLOC_CTX *ctx = talloc_tos();
2558 /* Split up the directory from the filename/mask. */
2559 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2560 &fname_dir, &fname_mask);
2561 if (!NT_STATUS_IS_OK(status)) {
2566 * We should only check the mangled cache
2567 * here if unix_convert failed. This means
2568 * that the path in 'mask' doesn't exist
2569 * on the file system and so we need to look
2570 * for a possible mangle. This patch from
2571 * Tine Smukavec <valentin.smukavec@hermes.si>.
2574 if (!VALID_STAT(smb_fname->st) &&
2575 mangle_is_mangled(fname_mask, conn->params)) {
2576 char *new_mask = NULL;
2577 mangle_lookup_name_from_8_3(ctx, fname_mask,
2578 &new_mask, conn->params);
2580 TALLOC_FREE(fname_mask);
2581 fname_mask = new_mask;
2588 * Only one file needs to be unlinked. Append the mask back
2589 * onto the directory.
2591 TALLOC_FREE(smb_fname->base_name);
2592 if (ISDOT(fname_dir)) {
2593 /* Ensure we use canonical names on open. */
2594 smb_fname->base_name = talloc_asprintf(smb_fname,
2598 smb_fname->base_name = talloc_asprintf(smb_fname,
2603 if (!smb_fname->base_name) {
2604 status = NT_STATUS_NO_MEMORY;
2608 dirtype = FILE_ATTRIBUTE_NORMAL;
2611 status = check_name(conn, smb_fname->base_name);
2612 if (!NT_STATUS_IS_OK(status)) {
2616 status = do_unlink(conn, req, smb_fname, dirtype);
2617 if (!NT_STATUS_IS_OK(status)) {
2623 struct smb_Dir *dir_hnd = NULL;
2625 const char *dname = NULL;
2626 char *talloced = NULL;
2628 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2629 status = NT_STATUS_OBJECT_NAME_INVALID;
2633 if (strequal(fname_mask,"????????.???")) {
2634 TALLOC_FREE(fname_mask);
2635 fname_mask = talloc_strdup(ctx, "*");
2637 status = NT_STATUS_NO_MEMORY;
2642 status = check_name(conn, fname_dir);
2643 if (!NT_STATUS_IS_OK(status)) {
2647 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2649 if (dir_hnd == NULL) {
2650 status = map_nt_error_from_unix(errno);
2654 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2655 the pattern matches against the long name, otherwise the short name
2656 We don't implement this yet XXXX
2659 status = NT_STATUS_NO_SUCH_FILE;
2661 while ((dname = ReadDirName(dir_hnd, &offset,
2662 &smb_fname->st, &talloced))) {
2663 TALLOC_CTX *frame = talloc_stackframe();
2665 if (!is_visible_file(conn, fname_dir, dname,
2666 &smb_fname->st, true)) {
2668 TALLOC_FREE(talloced);
2672 /* Quick check for "." and ".." */
2673 if (ISDOT(dname) || ISDOTDOT(dname)) {
2675 TALLOC_FREE(talloced);
2679 if(!mask_match(dname, fname_mask,
2680 conn->case_sensitive)) {
2682 TALLOC_FREE(talloced);
2686 TALLOC_FREE(smb_fname->base_name);
2687 if (ISDOT(fname_dir)) {
2688 /* Ensure we use canonical names on open. */
2689 smb_fname->base_name =
2690 talloc_asprintf(smb_fname, "%s",
2693 smb_fname->base_name =
2694 talloc_asprintf(smb_fname, "%s/%s",
2698 if (!smb_fname->base_name) {
2699 TALLOC_FREE(dir_hnd);
2700 status = NT_STATUS_NO_MEMORY;
2702 TALLOC_FREE(talloced);
2706 status = check_name(conn, smb_fname->base_name);
2707 if (!NT_STATUS_IS_OK(status)) {
2708 TALLOC_FREE(dir_hnd);
2710 TALLOC_FREE(talloced);
2714 status = do_unlink(conn, req, smb_fname, dirtype);
2715 if (!NT_STATUS_IS_OK(status)) {
2717 TALLOC_FREE(talloced);
2722 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2723 smb_fname->base_name));
2726 TALLOC_FREE(talloced);
2728 TALLOC_FREE(dir_hnd);
2731 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2732 status = map_nt_error_from_unix(errno);
2736 TALLOC_FREE(fname_dir);
2737 TALLOC_FREE(fname_mask);
2741 /****************************************************************************
2743 ****************************************************************************/
2745 void reply_unlink(struct smb_request *req)
2747 connection_struct *conn = req->conn;
2749 struct smb_filename *smb_fname = NULL;
2752 bool path_contains_wcard = False;
2753 TALLOC_CTX *ctx = talloc_tos();
2755 START_PROFILE(SMBunlink);
2758 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2762 dirtype = SVAL(req->vwv+0, 0);
2764 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2765 STR_TERMINATE, &status,
2766 &path_contains_wcard);
2767 if (!NT_STATUS_IS_OK(status)) {
2768 reply_nterror(req, status);
2772 status = filename_convert(ctx, conn,
2773 req->flags2 & FLAGS2_DFS_PATHNAMES,
2775 UCF_COND_ALLOW_WCARD_LCOMP,
2776 &path_contains_wcard,
2778 if (!NT_STATUS_IS_OK(status)) {
2779 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2780 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2781 ERRSRV, ERRbadpath);
2784 reply_nterror(req, status);
2788 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2790 status = unlink_internals(conn, req, dirtype, smb_fname,
2791 path_contains_wcard);
2792 if (!NT_STATUS_IS_OK(status)) {
2793 if (open_was_deferred(req->mid)) {
2794 /* We have re-scheduled this call. */
2797 reply_nterror(req, status);
2801 reply_outbuf(req, 0, 0);
2803 TALLOC_FREE(smb_fname);
2804 END_PROFILE(SMBunlink);
2808 /****************************************************************************
2810 ****************************************************************************/
2812 static void fail_readraw(void)
2814 const char *errstr = talloc_asprintf(talloc_tos(),
2815 "FAIL ! reply_readbraw: socket write fail (%s)",
2820 exit_server_cleanly(errstr);
2823 /****************************************************************************
2824 Fake (read/write) sendfile. Returns -1 on read or write fail.
2825 ****************************************************************************/
2827 ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread)
2830 size_t tosend = nread;
2837 bufsize = MIN(nread, 65536);
2839 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2843 while (tosend > 0) {
2847 if (tosend > bufsize) {
2852 ret = read_file(fsp,buf,startpos,cur_read);
2858 /* If we had a short read, fill with zeros. */
2859 if (ret < cur_read) {
2860 memset(buf + ret, '\0', cur_read - ret);
2863 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2865 char addr[INET6_ADDRSTRLEN];
2867 * Try and give an error message saying what
2870 DEBUG(0, ("write_data failed for client %s. "
2872 get_peer_addr(fsp->conn->sconn->sock, addr,
2879 startpos += cur_read;
2883 return (ssize_t)nread;
2886 /****************************************************************************
2887 Deal with the case of sendfile reading less bytes from the file than
2888 requested. Fill with zeros (all we can do).
2889 ****************************************************************************/
2891 void sendfile_short_send(files_struct *fsp,
2896 #define SHORT_SEND_BUFSIZE 1024
2897 if (nread < headersize) {
2898 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2899 "header for file %s (%s). Terminating\n",
2900 fsp_str_dbg(fsp), strerror(errno)));
2901 exit_server_cleanly("sendfile_short_send failed");
2904 nread -= headersize;
2906 if (nread < smb_maxcnt) {
2907 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2909 exit_server_cleanly("sendfile_short_send: "
2913 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2914 "with zeros !\n", fsp_str_dbg(fsp)));
2916 while (nread < smb_maxcnt) {
2918 * We asked for the real file size and told sendfile
2919 * to not go beyond the end of the file. But it can
2920 * happen that in between our fstat call and the
2921 * sendfile call the file was truncated. This is very
2922 * bad because we have already announced the larger
2923 * number of bytes to the client.
2925 * The best we can do now is to send 0-bytes, just as
2926 * a read from a hole in a sparse file would do.
2928 * This should happen rarely enough that I don't care
2929 * about efficiency here :-)
2933 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2934 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2936 char addr[INET6_ADDRSTRLEN];
2938 * Try and give an error message saying what
2941 DEBUG(0, ("write_data failed for client %s. "
2944 fsp->conn->sconn->sock, addr,
2947 exit_server_cleanly("sendfile_short_send: "
2948 "write_data failed");
2956 /****************************************************************************
2957 Return a readbraw error (4 bytes of zero).
2958 ****************************************************************************/
2960 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2966 smbd_lock_socket(sconn);
2967 if (write_data(sconn->sock,header,4) != 4) {
2968 char addr[INET6_ADDRSTRLEN];
2970 * Try and give an error message saying what
2973 DEBUG(0, ("write_data failed for client %s. "
2975 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2980 smbd_unlock_socket(sconn);
2983 /****************************************************************************
2984 Use sendfile in readbraw.
2985 ****************************************************************************/
2987 static void send_file_readbraw(connection_struct *conn,
2988 struct smb_request *req,
2994 struct smbd_server_connection *sconn = req->sconn;
2995 char *outbuf = NULL;
2999 * We can only use sendfile on a non-chained packet
3000 * but we can use on a non-oplocked file. tridge proved this
3001 * on a train in Germany :-). JRA.
3002 * reply_readbraw has already checked the length.
3005 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3006 (fsp->wcp == NULL) &&
3007 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3008 ssize_t sendfile_read = -1;
3010 DATA_BLOB header_blob;
3012 _smb_setlen(header,nread);
3013 header_blob = data_blob_const(header, 4);
3015 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3016 &header_blob, startpos,
3018 if (sendfile_read == -1) {
3019 /* Returning ENOSYS means no data at all was sent.
3020 * Do this as a normal read. */
3021 if (errno == ENOSYS) {
3022 goto normal_readbraw;
3026 * Special hack for broken Linux with no working sendfile. If we
3027 * return EINTR we sent the header but not the rest of the data.
3028 * Fake this up by doing read/write calls.
3030 if (errno == EINTR) {
3031 /* Ensure we don't do this again. */
3032 set_use_sendfile(SNUM(conn), False);
3033 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3035 if (fake_sendfile(fsp, startpos, nread) == -1) {
3036 DEBUG(0,("send_file_readbraw: "
3037 "fake_sendfile failed for "
3041 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3046 DEBUG(0,("send_file_readbraw: sendfile failed for "
3047 "file %s (%s). Terminating\n",
3048 fsp_str_dbg(fsp), strerror(errno)));
3049 exit_server_cleanly("send_file_readbraw sendfile failed");
3050 } else if (sendfile_read == 0) {
3052 * Some sendfile implementations return 0 to indicate
3053 * that there was a short read, but nothing was
3054 * actually written to the socket. In this case,
3055 * fallback to the normal read path so the header gets
3056 * the correct byte count.
3058 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3059 "bytes falling back to the normal read: "
3060 "%s\n", fsp_str_dbg(fsp)));
3061 goto normal_readbraw;
3064 /* Deal with possible short send. */
3065 if (sendfile_read != 4+nread) {
3066 sendfile_short_send(fsp, sendfile_read, 4, nread);
3073 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3075 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3076 (unsigned)(nread+4)));
3077 reply_readbraw_error(sconn);
3082 ret = read_file(fsp,outbuf+4,startpos,nread);
3083 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3092 _smb_setlen(outbuf,ret);
3093 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3094 char addr[INET6_ADDRSTRLEN];
3096 * Try and give an error message saying what
3099 DEBUG(0, ("write_data failed for client %s. "
3101 get_peer_addr(fsp->conn->sconn->sock, addr,
3108 TALLOC_FREE(outbuf);
3111 /****************************************************************************
3112 Reply to a readbraw (core+ protocol).
3113 ****************************************************************************/
3115 void reply_readbraw(struct smb_request *req)
3117 connection_struct *conn = req->conn;
3118 struct smbd_server_connection *sconn = req->sconn;
3119 ssize_t maxcount,mincount;
3123 struct lock_struct lock;
3126 START_PROFILE(SMBreadbraw);
3128 if (srv_is_signing_active(sconn) ||
3129 is_encrypted_packet(req->inbuf)) {
3130 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3131 "raw reads/writes are disallowed.");
3135 reply_readbraw_error(sconn);
3136 END_PROFILE(SMBreadbraw);
3140 if (sconn->smb1.echo_handler.trusted_fde) {
3141 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3142 "'async smb echo handler = yes'\n"));
3143 reply_readbraw_error(sconn);
3144 END_PROFILE(SMBreadbraw);
3149 * Special check if an oplock break has been issued
3150 * and the readraw request croses on the wire, we must
3151 * return a zero length response here.
3154 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3157 * We have to do a check_fsp by hand here, as
3158 * we must always return 4 zero bytes on error,
3162 if (!fsp || !conn || conn != fsp->conn ||
3163 req->vuid != fsp->vuid ||
3164 fsp->is_directory || fsp->fh->fd == -1) {
3166 * fsp could be NULL here so use the value from the packet. JRA.
3168 DEBUG(3,("reply_readbraw: fnum %d not valid "
3170 (int)SVAL(req->vwv+0, 0)));
3171 reply_readbraw_error(sconn);
3172 END_PROFILE(SMBreadbraw);
3176 /* Do a "by hand" version of CHECK_READ. */
3177 if (!(fsp->can_read ||
3178 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3179 (fsp->access_mask & FILE_EXECUTE)))) {
3180 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3181 (int)SVAL(req->vwv+0, 0)));
3182 reply_readbraw_error(sconn);
3183 END_PROFILE(SMBreadbraw);
3187 flush_write_cache(fsp, READRAW_FLUSH);
3189 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3190 if(req->wct == 10) {
3192 * This is a large offset (64 bit) read.
3194 #ifdef LARGE_SMB_OFF_T
3196 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3198 #else /* !LARGE_SMB_OFF_T */
3201 * Ensure we haven't been sent a >32 bit offset.
3204 if(IVAL(req->vwv+8, 0) != 0) {
3205 DEBUG(0,("reply_readbraw: large offset "
3206 "(%x << 32) used and we don't support "
3207 "64 bit offsets.\n",
3208 (unsigned int)IVAL(req->vwv+8, 0) ));
3209 reply_readbraw_error();
3210 END_PROFILE(SMBreadbraw);
3214 #endif /* LARGE_SMB_OFF_T */
3217 DEBUG(0,("reply_readbraw: negative 64 bit "
3218 "readraw offset (%.0f) !\n",
3219 (double)startpos ));
3220 reply_readbraw_error(sconn);
3221 END_PROFILE(SMBreadbraw);
3226 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3227 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3229 /* ensure we don't overrun the packet size */
3230 maxcount = MIN(65535,maxcount);
3232 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3233 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3236 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3237 reply_readbraw_error(sconn);
3238 END_PROFILE(SMBreadbraw);
3242 if (fsp_stat(fsp) == 0) {
3243 size = fsp->fsp_name->st.st_ex_size;
3246 if (startpos >= size) {
3249 nread = MIN(maxcount,(size - startpos));
3252 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3253 if (nread < mincount)
3257 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3258 "min=%lu nread=%lu\n",
3259 fsp->fnum, (double)startpos,
3260 (unsigned long)maxcount,
3261 (unsigned long)mincount,
3262 (unsigned long)nread ) );
3264 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3266 DEBUG(5,("reply_readbraw finished\n"));
3268 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3270 END_PROFILE(SMBreadbraw);
3275 #define DBGC_CLASS DBGC_LOCKING
3277 /****************************************************************************
3278 Reply to a lockread (core+ protocol).
3279 ****************************************************************************/
3281 void reply_lockread(struct smb_request *req)
3283 connection_struct *conn = req->conn;
3290 struct byte_range_lock *br_lck = NULL;
3292 struct smbd_server_connection *sconn = req->sconn;
3294 START_PROFILE(SMBlockread);
3297 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3298 END_PROFILE(SMBlockread);
3302 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3304 if (!check_fsp(conn, req, fsp)) {
3305 END_PROFILE(SMBlockread);
3309 if (!CHECK_READ(fsp,req)) {
3310 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3311 END_PROFILE(SMBlockread);
3315 numtoread = SVAL(req->vwv+1, 0);
3316 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3318 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3320 reply_outbuf(req, 5, numtoread + 3);
3322 data = smb_buf(req->outbuf) + 3;
3325 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3326 * protocol request that predates the read/write lock concept.
3327 * Thus instead of asking for a read lock here we need to ask
3328 * for a write lock. JRA.
3329 * Note that the requested lock size is unaffected by max_recv.
3332 br_lck = do_lock(req->sconn->msg_ctx,
3334 (uint64_t)req->smbpid,
3335 (uint64_t)numtoread,
3339 False, /* Non-blocking lock. */
3343 TALLOC_FREE(br_lck);
3345 if (NT_STATUS_V(status)) {
3346 reply_nterror(req, status);
3347 END_PROFILE(SMBlockread);
3352 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3355 if (numtoread > sconn->smb1.negprot.max_recv) {
3356 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3357 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3358 (unsigned int)numtoread,
3359 (unsigned int)sconn->smb1.negprot.max_recv));
3360 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3362 nread = read_file(fsp,data,startpos,numtoread);
3365 reply_nterror(req, map_nt_error_from_unix(errno));
3366 END_PROFILE(SMBlockread);
3370 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3372 SSVAL(req->outbuf,smb_vwv0,nread);
3373 SSVAL(req->outbuf,smb_vwv5,nread+3);
3374 p = smb_buf(req->outbuf);
3375 SCVAL(p,0,0); /* pad byte. */
3378 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3379 fsp->fnum, (int)numtoread, (int)nread));
3381 END_PROFILE(SMBlockread);
3386 #define DBGC_CLASS DBGC_ALL
3388 /****************************************************************************
3390 ****************************************************************************/
3392 void reply_read(struct smb_request *req)
3394 connection_struct *conn = req->conn;
3401 struct lock_struct lock;
3402 struct smbd_server_connection *sconn = req->sconn;
3404 START_PROFILE(SMBread);
3407 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3408 END_PROFILE(SMBread);
3412 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3414 if (!check_fsp(conn, req, fsp)) {
3415 END_PROFILE(SMBread);
3419 if (!CHECK_READ(fsp,req)) {
3420 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3421 END_PROFILE(SMBread);
3425 numtoread = SVAL(req->vwv+1, 0);
3426 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3428 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3431 * The requested read size cannot be greater than max_recv. JRA.
3433 if (numtoread > sconn->smb1.negprot.max_recv) {
3434 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3435 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3436 (unsigned int)numtoread,
3437 (unsigned int)sconn->smb1.negprot.max_recv));
3438 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3441 reply_outbuf(req, 5, numtoread+3);
3443 data = smb_buf(req->outbuf) + 3;
3445 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3446 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3449 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3450 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3451 END_PROFILE(SMBread);
3456 nread = read_file(fsp,data,startpos,numtoread);
3459 reply_nterror(req, map_nt_error_from_unix(errno));
3463 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3465 SSVAL(req->outbuf,smb_vwv0,nread);
3466 SSVAL(req->outbuf,smb_vwv5,nread+3);
3467 SCVAL(smb_buf(req->outbuf),0,1);
3468 SSVAL(smb_buf(req->outbuf),1,nread);
3470 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3471 fsp->fnum, (int)numtoread, (int)nread ) );
3474 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3476 END_PROFILE(SMBread);
3480 /****************************************************************************
3482 ****************************************************************************/
3484 static int setup_readX_header(struct smb_request *req, char *outbuf,
3490 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3491 data = smb_buf(outbuf);
3493 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3495 SCVAL(outbuf,smb_vwv0,0xFF);
3496 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3497 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3498 SSVAL(outbuf,smb_vwv6,
3500 + 1 /* the wct field */
3501 + 12 * sizeof(uint16_t) /* vwv */
3502 + 2); /* the buflen field */
3503 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3504 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3505 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3506 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3510 /****************************************************************************
3511 Reply to a read and X - possibly using sendfile.
3512 ****************************************************************************/
3514 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3515 files_struct *fsp, SMB_OFF_T startpos,
3519 struct lock_struct lock;
3520 int saved_errno = 0;
3522 if(fsp_stat(fsp) == -1) {
3523 reply_nterror(req, map_nt_error_from_unix(errno));
3527 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3528 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3531 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3532 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3536 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3537 (startpos > fsp->fsp_name->st.st_ex_size)
3538 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3540 * We already know that we would do a short read, so don't
3541 * try the sendfile() path.
3543 goto nosendfile_read;
3547 * We can only use sendfile on a non-chained packet
3548 * but we can use on a non-oplocked file. tridge proved this
3549 * on a train in Germany :-). JRA.
3552 if (!req_is_in_chain(req) &&
3553 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3554 (fsp->wcp == NULL) &&
3555 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3556 uint8 headerbuf[smb_size + 12 * 2];
3560 * Set up the packet header before send. We
3561 * assume here the sendfile will work (get the
3562 * correct amount of data).
3565 header = data_blob_const(headerbuf, sizeof(headerbuf));
3567 construct_reply_common_req(req, (char *)headerbuf);
3568 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3570 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3571 startpos, smb_maxcnt);
3573 /* Returning ENOSYS means no data at all was sent.
3574 Do this as a normal read. */
3575 if (errno == ENOSYS) {
3580 * Special hack for broken Linux with no working sendfile. If we
3581 * return EINTR we sent the header but not the rest of the data.
3582 * Fake this up by doing read/write calls.
3585 if (errno == EINTR) {
3586 /* Ensure we don't do this again. */
3587 set_use_sendfile(SNUM(conn), False);
3588 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3589 nread = fake_sendfile(fsp, startpos,
3592 DEBUG(0,("send_file_readX: "
3593 "fake_sendfile failed for "
3597 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3599 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3600 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3601 /* No outbuf here means successful sendfile. */
3605 DEBUG(0,("send_file_readX: sendfile failed for file "
3606 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3608 exit_server_cleanly("send_file_readX sendfile failed");
3609 } else if (nread == 0) {
3611 * Some sendfile implementations return 0 to indicate
3612 * that there was a short read, but nothing was
3613 * actually written to the socket. In this case,
3614 * fallback to the normal read path so the header gets
3615 * the correct byte count.
3617 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3618 "falling back to the normal read: %s\n",
3623 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3624 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3626 /* Deal with possible short send. */
3627 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3628 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3630 /* No outbuf here means successful sendfile. */
3631 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3632 SMB_PERFCOUNT_END(&req->pcd);
3638 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3639 uint8 headerbuf[smb_size + 2*12];
3641 construct_reply_common_req(req, (char *)headerbuf);
3642 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3644 /* Send out the header. */
3645 if (write_data(req->sconn->sock, (char *)headerbuf,
3646 sizeof(headerbuf)) != sizeof(headerbuf)) {
3648 char addr[INET6_ADDRSTRLEN];
3650 * Try and give an error message saying what
3653 DEBUG(0, ("write_data failed for client %s. "
3655 get_peer_addr(req->sconn->sock, addr,
3659 DEBUG(0,("send_file_readX: write_data failed for file "
3660 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3662 exit_server_cleanly("send_file_readX sendfile failed");
3664 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3666 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3667 "file %s (%s).\n", fsp_str_dbg(fsp),
3669 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3676 reply_outbuf(req, 12, smb_maxcnt);
3678 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3679 saved_errno = errno;
3681 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3684 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3688 setup_readX_header(req, (char *)req->outbuf, nread);
3690 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3691 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3697 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3698 TALLOC_FREE(req->outbuf);
3702 /****************************************************************************
3703 Reply to a read and X.
3704 ****************************************************************************/
3706 void reply_read_and_X(struct smb_request *req)
3708 connection_struct *conn = req->conn;
3712 bool big_readX = False;
3714 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3717 START_PROFILE(SMBreadX);
3719 if ((req->wct != 10) && (req->wct != 12)) {
3720 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3724 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3725 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3726 smb_maxcnt = SVAL(req->vwv+5, 0);
3728 /* If it's an IPC, pass off the pipe handler. */
3730 reply_pipe_read_and_X(req);
3731 END_PROFILE(SMBreadX);
3735 if (!check_fsp(conn, req, fsp)) {
3736 END_PROFILE(SMBreadX);
3740 if (!CHECK_READ(fsp,req)) {
3741 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3742 END_PROFILE(SMBreadX);
3746 if (global_client_caps & CAP_LARGE_READX) {
3747 size_t upper_size = SVAL(req->vwv+7, 0);
3748 smb_maxcnt |= (upper_size<<16);
3749 if (upper_size > 1) {
3750 /* Can't do this on a chained packet. */
3751 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3752 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3753 END_PROFILE(SMBreadX);
3756 /* We currently don't do this on signed or sealed data. */
3757 if (srv_is_signing_active(req->sconn) ||
3758 is_encrypted_packet(req->inbuf)) {
3759 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3760 END_PROFILE(SMBreadX);
3763 /* Is there room in the reply for this data ? */
3764 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3766 NT_STATUS_INVALID_PARAMETER);
3767 END_PROFILE(SMBreadX);
3774 if (req->wct == 12) {
3775 #ifdef LARGE_SMB_OFF_T
3777 * This is a large offset (64 bit) read.
3779 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3781 #else /* !LARGE_SMB_OFF_T */
3784 * Ensure we haven't been sent a >32 bit offset.
3787 if(IVAL(req->vwv+10, 0) != 0) {
3788 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3789 "used and we don't support 64 bit offsets.\n",
3790 (unsigned int)IVAL(req->vwv+10, 0) ));
3791 END_PROFILE(SMBreadX);
3792 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3796 #endif /* LARGE_SMB_OFF_T */
3801 NTSTATUS status = schedule_aio_read_and_X(conn,
3806 if (NT_STATUS_IS_OK(status)) {
3807 /* Read scheduled - we're done. */
3810 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3811 /* Real error - report to client. */
3812 END_PROFILE(SMBreadX);
3813 reply_nterror(req, status);
3816 /* NT_STATUS_RETRY - fall back to sync read. */
3819 smbd_lock_socket(req->sconn);
3820 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3821 smbd_unlock_socket(req->sconn);
3824 END_PROFILE(SMBreadX);
3828 /****************************************************************************
3829 Error replies to writebraw must have smb_wct == 1. Fix this up.
3830 ****************************************************************************/
3832 void error_to_writebrawerr(struct smb_request *req)
3834 uint8 *old_outbuf = req->outbuf;
3836 reply_outbuf(req, 1, 0);
3838 memcpy(req->outbuf, old_outbuf, smb_size);
3839 TALLOC_FREE(old_outbuf);
3842 /****************************************************************************
3843 Read 4 bytes of a smb packet and return the smb length of the packet.
3844 Store the result in the buffer. This version of the function will
3845 never return a session keepalive (length of zero).
3846 Timeout is in milliseconds.
3847 ****************************************************************************/
3849 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3852 uint8_t msgtype = SMBkeepalive;
3854 while (msgtype == SMBkeepalive) {
3857 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3859 if (!NT_STATUS_IS_OK(status)) {
3860 char addr[INET6_ADDRSTRLEN];
3861 /* Try and give an error message
3862 * saying what client failed. */
3863 DEBUG(0, ("read_fd_with_timeout failed for "
3864 "client %s read error = %s.\n",
3865 get_peer_addr(fd,addr,sizeof(addr)),
3866 nt_errstr(status)));
3870 msgtype = CVAL(inbuf, 0);
3873 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3874 (unsigned long)len));
3876 return NT_STATUS_OK;
3879 /****************************************************************************
3880 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3881 ****************************************************************************/
3883 void reply_writebraw(struct smb_request *req)
3885 connection_struct *conn = req->conn;
3888 ssize_t total_written=0;
3889 size_t numtowrite=0;
3895 struct lock_struct lock;
3898 START_PROFILE(SMBwritebraw);
3901 * If we ever reply with an error, it must have the SMB command
3902 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3905 SCVAL(req->inbuf,smb_com,SMBwritec);
3907 if (srv_is_signing_active(req->sconn)) {
3908 END_PROFILE(SMBwritebraw);
3909 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3910 "raw reads/writes are disallowed.");
3913 if (req->wct < 12) {
3914 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3915 error_to_writebrawerr(req);
3916 END_PROFILE(SMBwritebraw);
3920 if (req->sconn->smb1.echo_handler.trusted_fde) {
3921 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3922 "'async smb echo handler = yes'\n"));
3923 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3924 error_to_writebrawerr(req);
3925 END_PROFILE(SMBwritebraw);
3929 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3930 if (!check_fsp(conn, req, fsp)) {
3931 error_to_writebrawerr(req);
3932 END_PROFILE(SMBwritebraw);
3936 if (!CHECK_WRITE(fsp)) {
3937 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3938 error_to_writebrawerr(req);
3939 END_PROFILE(SMBwritebraw);
3943 tcount = IVAL(req->vwv+1, 0);
3944 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3945 write_through = BITSETW(req->vwv+7,0);
3947 /* We have to deal with slightly different formats depending
3948 on whether we are using the core+ or lanman1.0 protocol */
3950 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3951 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3952 data = smb_buf(req->inbuf);
3954 numtowrite = SVAL(req->vwv+10, 0);
3955 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3958 /* Ensure we don't write bytes past the end of this packet. */
3959 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3960 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3961 error_to_writebrawerr(req);
3962 END_PROFILE(SMBwritebraw);
3966 if (!fsp->print_file) {
3967 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3968 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3971 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3972 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3973 error_to_writebrawerr(req);
3974 END_PROFILE(SMBwritebraw);
3980 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3983 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3984 "wrote=%d sync=%d\n",
3985 fsp->fnum, (double)startpos, (int)numtowrite,
3986 (int)nwritten, (int)write_through));
3988 if (nwritten < (ssize_t)numtowrite) {
3989 reply_nterror(req, NT_STATUS_DISK_FULL);
3990 error_to_writebrawerr(req);
3994 total_written = nwritten;
3996 /* Allocate a buffer of 64k + length. */
3997 buf = TALLOC_ARRAY(NULL, char, 65540);
3999 reply_nterror(req, NT_STATUS_NO_MEMORY);
4000 error_to_writebrawerr(req);
4004 /* Return a SMBwritebraw message to the redirector to tell
4005 * it to send more bytes */
4007 memcpy(buf, req->inbuf, smb_size);
4008 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4009 SCVAL(buf,smb_com,SMBwritebraw);
4010 SSVALS(buf,smb_vwv0,0xFFFF);
4012 if (!srv_send_smb(req->sconn,
4014 false, 0, /* no signing */
4015 IS_CONN_ENCRYPTED(conn),
4017 exit_server_cleanly("reply_writebraw: srv_send_smb "
4021 /* Now read the raw data into the buffer and write it */
4022 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4024 if (!NT_STATUS_IS_OK(status)) {
4025 exit_server_cleanly("secondary writebraw failed");
4028 /* Set up outbuf to return the correct size */
4029 reply_outbuf(req, 1, 0);
4031 if (numtowrite != 0) {
4033 if (numtowrite > 0xFFFF) {
4034 DEBUG(0,("reply_writebraw: Oversize secondary write "
4035 "raw requested (%u). Terminating\n",
4036 (unsigned int)numtowrite ));
4037 exit_server_cleanly("secondary writebraw failed");
4040 if (tcount > nwritten+numtowrite) {
4041 DEBUG(3,("reply_writebraw: Client overestimated the "
4043 (int)tcount,(int)nwritten,(int)numtowrite));
4046 status = read_data(req->sconn->sock, buf+4, numtowrite);
4048 if (!NT_STATUS_IS_OK(status)) {
4049 char addr[INET6_ADDRSTRLEN];
4050 /* Try and give an error message
4051 * saying what client failed. */
4052 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4053 "raw read failed (%s) for client %s. "
4054 "Terminating\n", nt_errstr(status),
4055 get_peer_addr(req->sconn->sock, addr,
4057 exit_server_cleanly("secondary writebraw failed");
4060 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4061 if (nwritten == -1) {
4063 reply_nterror(req, map_nt_error_from_unix(errno));
4064 error_to_writebrawerr(req);
4068 if (nwritten < (ssize_t)numtowrite) {
4069 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4070 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4074 total_written += nwritten;
4079 SSVAL(req->outbuf,smb_vwv0,total_written);
4081 status = sync_file(conn, fsp, write_through);
4082 if (!NT_STATUS_IS_OK(status)) {
4083 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4084 fsp_str_dbg(fsp), nt_errstr(status)));
4085 reply_nterror(req, status);
4086 error_to_writebrawerr(req);
4090 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4092 fsp->fnum, (double)startpos, (int)numtowrite,
4093 (int)total_written));
4095 if (!fsp->print_file) {
4096 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4099 /* We won't return a status if write through is not selected - this
4100 * follows what WfWg does */
4101 END_PROFILE(SMBwritebraw);
4103 if (!write_through && total_written==tcount) {
4105 #if RABBIT_PELLET_FIX
4107 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4108 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
4111 if (!send_keepalive(req->sconn->sock)) {
4112 exit_server_cleanly("reply_writebraw: send of "
4113 "keepalive failed");
4116 TALLOC_FREE(req->outbuf);
4121 if (!fsp->print_file) {
4122 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4125 END_PROFILE(SMBwritebraw);
4130 #define DBGC_CLASS DBGC_LOCKING
4132 /****************************************************************************
4133 Reply to a writeunlock (core+).
4134 ****************************************************************************/
4136 void reply_writeunlock(struct smb_request *req)
4138 connection_struct *conn = req->conn;
4139 ssize_t nwritten = -1;
4143 NTSTATUS status = NT_STATUS_OK;
4145 struct lock_struct lock;
4146 int saved_errno = 0;
4148 START_PROFILE(SMBwriteunlock);
4151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4152 END_PROFILE(SMBwriteunlock);
4156 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4158 if (!check_fsp(conn, req, fsp)) {
4159 END_PROFILE(SMBwriteunlock);
4163 if (!CHECK_WRITE(fsp)) {
4164 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4165 END_PROFILE(SMBwriteunlock);
4169 numtowrite = SVAL(req->vwv+1, 0);
4170 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4171 data = (const char *)req->buf + 3;
4173 if (!fsp->print_file && numtowrite > 0) {
4174 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4175 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4178 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4179 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4180 END_PROFILE(SMBwriteunlock);
4185 /* The special X/Open SMB protocol handling of
4186 zero length writes is *NOT* done for
4188 if(numtowrite == 0) {
4191 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4192 saved_errno = errno;
4195 status = sync_file(conn, fsp, False /* write through */);
4196 if (!NT_STATUS_IS_OK(status)) {
4197 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4198 fsp_str_dbg(fsp), nt_errstr(status)));
4199 reply_nterror(req, status);
4204 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4208 if((nwritten < numtowrite) && (numtowrite != 0)) {
4209 reply_nterror(req, NT_STATUS_DISK_FULL);
4213 if (numtowrite && !fsp->print_file) {
4214 status = do_unlock(req->sconn->msg_ctx,
4216 (uint64_t)req->smbpid,
4217 (uint64_t)numtowrite,
4221 if (NT_STATUS_V(status)) {
4222 reply_nterror(req, status);
4227 reply_outbuf(req, 1, 0);
4229 SSVAL(req->outbuf,smb_vwv0,nwritten);
4231 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4232 fsp->fnum, (int)numtowrite, (int)nwritten));
4235 if (numtowrite && !fsp->print_file) {
4236 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4239 END_PROFILE(SMBwriteunlock);
4244 #define DBGC_CLASS DBGC_ALL
4246 /****************************************************************************
4248 ****************************************************************************/
4250 void reply_write(struct smb_request *req)
4252 connection_struct *conn = req->conn;
4254 ssize_t nwritten = -1;
4258 struct lock_struct lock;
4260 int saved_errno = 0;
4262 START_PROFILE(SMBwrite);
4265 END_PROFILE(SMBwrite);
4266 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4270 /* If it's an IPC, pass off the pipe handler. */
4272 reply_pipe_write(req);
4273 END_PROFILE(SMBwrite);
4277 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4279 if (!check_fsp(conn, req, fsp)) {
4280 END_PROFILE(SMBwrite);
4284 if (!CHECK_WRITE(fsp)) {
4285 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4286 END_PROFILE(SMBwrite);
4290 numtowrite = SVAL(req->vwv+1, 0);
4291 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4292 data = (const char *)req->buf + 3;
4294 if (!fsp->print_file) {
4295 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4296 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4299 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4300 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4301 END_PROFILE(SMBwrite);
4307 * X/Open SMB protocol says that if smb_vwv1 is
4308 * zero then the file size should be extended or
4309 * truncated to the size given in smb_vwv[2-3].
4312 if(numtowrite == 0) {
4314 * This is actually an allocate call, and set EOF. JRA.
4316 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4318 reply_nterror(req, NT_STATUS_DISK_FULL);
4321 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4323 reply_nterror(req, NT_STATUS_DISK_FULL);
4326 trigger_write_time_update_immediate(fsp);
4328 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4331 status = sync_file(conn, fsp, False);
4332 if (!NT_STATUS_IS_OK(status)) {
4333 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4334 fsp_str_dbg(fsp), nt_errstr(status)));
4335 reply_nterror(req, status);
4340 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4344 if((nwritten == 0) && (numtowrite != 0)) {
4345 reply_nterror(req, NT_STATUS_DISK_FULL);
4349 reply_outbuf(req, 1, 0);
4351 SSVAL(req->outbuf,smb_vwv0,nwritten);
4353 if (nwritten < (ssize_t)numtowrite) {
4354 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4355 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4358 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4361 if (!fsp->print_file) {
4362 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4365 END_PROFILE(SMBwrite);
4369 /****************************************************************************
4370 Ensure a buffer is a valid writeX for recvfile purposes.
4371 ****************************************************************************/
4373 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4374 (2*14) + /* word count (including bcc) */ \
4377 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4378 const uint8_t *inbuf)
4381 connection_struct *conn = NULL;
4382 unsigned int doff = 0;
4383 size_t len = smb_len_large(inbuf);
4385 if (is_encrypted_packet(inbuf)) {
4386 /* Can't do this on encrypted
4391 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4395 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4396 CVAL(inbuf,smb_wct) != 14) {
4397 DEBUG(10,("is_valid_writeX_buffer: chained or "
4398 "invalid word length.\n"));
4402 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4404 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4408 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4411 if (IS_PRINT(conn)) {
4412 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4415 doff = SVAL(inbuf,smb_vwv11);
4417 numtowrite = SVAL(inbuf,smb_vwv10);
4419 if (len > doff && len - doff > 0xFFFF) {
4420 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4423 if (numtowrite == 0) {
4424 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4428 /* Ensure the sizes match up. */
4429 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4430 /* no pad byte...old smbclient :-( */
4431 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4433 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4437 if (len - doff != numtowrite) {
4438 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4439 "len = %u, doff = %u, numtowrite = %u\n",
4442 (unsigned int)numtowrite ));
4446 DEBUG(10,("is_valid_writeX_buffer: true "
4447 "len = %u, doff = %u, numtowrite = %u\n",
4450 (unsigned int)numtowrite ));
4455 /****************************************************************************
4456 Reply to a write and X.
4457 ****************************************************************************/
4459 void reply_write_and_X(struct smb_request *req)
4461 connection_struct *conn = req->conn;
4463 struct lock_struct lock;
4468 unsigned int smb_doff;
4469 unsigned int smblen;
4472 int saved_errno = 0;
4474 START_PROFILE(SMBwriteX);
4476 if ((req->wct != 12) && (req->wct != 14)) {
4477 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4478 END_PROFILE(SMBwriteX);
4482 numtowrite = SVAL(req->vwv+10, 0);
4483 smb_doff = SVAL(req->vwv+11, 0);
4484 smblen = smb_len(req->inbuf);
4486 if (req->unread_bytes > 0xFFFF ||
4487 (smblen > smb_doff &&
4488 smblen - smb_doff > 0xFFFF)) {
4489 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4492 if (req->unread_bytes) {
4493 /* Can't do a recvfile write on IPC$ */
4495 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4496 END_PROFILE(SMBwriteX);
4499 if (numtowrite != req->unread_bytes) {
4500 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4501 END_PROFILE(SMBwriteX);
4505 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4506 smb_doff + numtowrite > smblen) {
4507 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4508 END_PROFILE(SMBwriteX);
4513 /* If it's an IPC, pass off the pipe handler. */
4515 if (req->unread_bytes) {
4516 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4517 END_PROFILE(SMBwriteX);
4520 reply_pipe_write_and_X(req);
4521 END_PROFILE(SMBwriteX);
4525 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4526 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4527 write_through = BITSETW(req->vwv+7,0);
4529 if (!check_fsp(conn, req, fsp)) {
4530 END_PROFILE(SMBwriteX);
4534 if (!CHECK_WRITE(fsp)) {
4535 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4536 END_PROFILE(SMBwriteX);
4540 data = smb_base(req->inbuf) + smb_doff;
4542 if(req->wct == 14) {
4543 #ifdef LARGE_SMB_OFF_T
4545 * This is a large offset (64 bit) write.
4547 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4549 #else /* !LARGE_SMB_OFF_T */
4552 * Ensure we haven't been sent a >32 bit offset.
4555 if(IVAL(req->vwv+12, 0) != 0) {
4556 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4557 "used and we don't support 64 bit offsets.\n",
4558 (unsigned int)IVAL(req->vwv+12, 0) ));
4559 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4560 END_PROFILE(SMBwriteX);
4564 #endif /* LARGE_SMB_OFF_T */
4567 /* X/Open SMB protocol says that, unlike SMBwrite
4568 if the length is zero then NO truncation is
4569 done, just a write of zero. To truncate a file,
4572 if(numtowrite == 0) {
4575 if (req->unread_bytes == 0) {
4576 status = schedule_aio_write_and_X(conn,
4583 if (NT_STATUS_IS_OK(status)) {
4584 /* write scheduled - we're done. */
4587 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4588 /* Real error - report to client. */
4589 reply_nterror(req, status);
4592 /* NT_STATUS_RETRY - fall through to sync write. */
4595 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4596 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4599 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4600 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4604 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4605 saved_errno = errno;
4607 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4611 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4615 if((nwritten == 0) && (numtowrite != 0)) {
4616 reply_nterror(req, NT_STATUS_DISK_FULL);
4620 reply_outbuf(req, 6, 0);
4621 SSVAL(req->outbuf,smb_vwv2,nwritten);
4622 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4624 if (nwritten < (ssize_t)numtowrite) {
4625 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4626 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4629 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4630 fsp->fnum, (int)numtowrite, (int)nwritten));
4632 status = sync_file(conn, fsp, write_through);
4633 if (!NT_STATUS_IS_OK(status)) {
4634 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4635 fsp_str_dbg(fsp), nt_errstr(status)));
4636 reply_nterror(req, status);
4640 END_PROFILE(SMBwriteX);
4645 END_PROFILE(SMBwriteX);
4649 /****************************************************************************
4651 ****************************************************************************/
4653 void reply_lseek(struct smb_request *req)
4655 connection_struct *conn = req->conn;
4661 START_PROFILE(SMBlseek);
4664 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4665 END_PROFILE(SMBlseek);
4669 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4671 if (!check_fsp(conn, req, fsp)) {
4675 flush_write_cache(fsp, SEEK_FLUSH);
4677 mode = SVAL(req->vwv+1, 0) & 3;
4678 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4679 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4688 res = fsp->fh->pos + startpos;
4699 if (umode == SEEK_END) {
4700 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4701 if(errno == EINVAL) {
4702 SMB_OFF_T current_pos = startpos;
4704 if(fsp_stat(fsp) == -1) {
4706 map_nt_error_from_unix(errno));
4707 END_PROFILE(SMBlseek);
4711 current_pos += fsp->fsp_name->st.st_ex_size;
4713 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4718 reply_nterror(req, map_nt_error_from_unix(errno));
4719 END_PROFILE(SMBlseek);
4726 reply_outbuf(req, 2, 0);
4727 SIVAL(req->outbuf,smb_vwv0,res);
4729 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4730 fsp->fnum, (double)startpos, (double)res, mode));
4732 END_PROFILE(SMBlseek);
4736 /****************************************************************************
4738 ****************************************************************************/
4740 void reply_flush(struct smb_request *req)
4742 connection_struct *conn = req->conn;
4746 START_PROFILE(SMBflush);
4749 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4753 fnum = SVAL(req->vwv+0, 0);
4754 fsp = file_fsp(req, fnum);
4756 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4761 file_sync_all(conn);
4763 NTSTATUS status = sync_file(conn, fsp, True);
4764 if (!NT_STATUS_IS_OK(status)) {
4765 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4766 fsp_str_dbg(fsp), nt_errstr(status)));
4767 reply_nterror(req, status);
4768 END_PROFILE(SMBflush);
4773 reply_outbuf(req, 0, 0);
4775 DEBUG(3,("flush\n"));
4776 END_PROFILE(SMBflush);
4780 /****************************************************************************
4782 conn POINTER CAN BE NULL HERE !
4783 ****************************************************************************/
4785 void reply_exit(struct smb_request *req)
4787 START_PROFILE(SMBexit);
4789 file_close_pid(req->sconn, req->smbpid, req->vuid);
4791 reply_outbuf(req, 0, 0);
4793 DEBUG(3,("exit\n"));
4795 END_PROFILE(SMBexit);
4799 /****************************************************************************
4800 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4801 ****************************************************************************/
4803 void reply_close(struct smb_request *req)
4805 connection_struct *conn = req->conn;
4806 NTSTATUS status = NT_STATUS_OK;
4807 files_struct *fsp = NULL;
4808 START_PROFILE(SMBclose);
4811 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4812 END_PROFILE(SMBclose);
4816 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4819 * We can only use check_fsp if we know it's not a directory.
4822 if (!check_fsp_open(conn, req, fsp)) {
4823 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4824 END_PROFILE(SMBclose);
4828 if(fsp->is_directory) {
4830 * Special case - close NT SMB directory handle.
4832 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4833 status = close_file(req, fsp, NORMAL_CLOSE);
4837 * Close ordinary file.
4840 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4841 fsp->fh->fd, fsp->fnum,
4842 conn->num_files_open));
4845 * Take care of any time sent in the close.
4848 t = srv_make_unix_date3(req->vwv+1);
4849 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4852 * close_file() returns the unix errno if an error
4853 * was detected on close - normally this is due to
4854 * a disk full error. If not then it was probably an I/O error.
4857 status = close_file(req, fsp, NORMAL_CLOSE);
4860 if (!NT_STATUS_IS_OK(status)) {
4861 reply_nterror(req, status);
4862 END_PROFILE(SMBclose);
4866 reply_outbuf(req, 0, 0);
4867 END_PROFILE(SMBclose);
4871 /****************************************************************************
4872 Reply to a writeclose (Core+ protocol).
4873 ****************************************************************************/
4875 void reply_writeclose(struct smb_request *req)
4877 connection_struct *conn = req->conn;
4879 ssize_t nwritten = -1;
4880 NTSTATUS close_status = NT_STATUS_OK;
4883 struct timespec mtime;
4885 struct lock_struct lock;
4887 START_PROFILE(SMBwriteclose);
4890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4891 END_PROFILE(SMBwriteclose);
4895 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4897 if (!check_fsp(conn, req, fsp)) {
4898 END_PROFILE(SMBwriteclose);
4901 if (!CHECK_WRITE(fsp)) {
4902 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4903 END_PROFILE(SMBwriteclose);
4907 numtowrite = SVAL(req->vwv+1, 0);
4908 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4909 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4910 data = (const char *)req->buf + 1;
4912 if (!fsp->print_file) {
4913 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4914 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4917 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4918 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4919 END_PROFILE(SMBwriteclose);
4924 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4926 set_close_write_time(fsp, mtime);
4929 * More insanity. W2K only closes the file if writelen > 0.
4934 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4935 "file %s\n", fsp_str_dbg(fsp)));
4936 close_status = close_file(req, fsp, NORMAL_CLOSE);
4939 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4940 fsp->fnum, (int)numtowrite, (int)nwritten,
4941 conn->num_files_open));
4943 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4944 reply_nterror(req, NT_STATUS_DISK_FULL);
4948 if(!NT_STATUS_IS_OK(close_status)) {
4949 reply_nterror(req, close_status);
4953 reply_outbuf(req, 1, 0);
4955 SSVAL(req->outbuf,smb_vwv0,nwritten);
4958 if (numtowrite && !fsp->print_file) {
4959 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4962 END_PROFILE(SMBwriteclose);
4967 #define DBGC_CLASS DBGC_LOCKING
4969 /****************************************************************************
4971 ****************************************************************************/
4973 void reply_lock(struct smb_request *req)
4975 connection_struct *conn = req->conn;
4976 uint64_t count,offset;
4979 struct byte_range_lock *br_lck = NULL;
4981 START_PROFILE(SMBlock);
4984 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4985 END_PROFILE(SMBlock);
4989 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4991 if (!check_fsp(conn, req, fsp)) {
4992 END_PROFILE(SMBlock);
4996 count = (uint64_t)IVAL(req->vwv+1, 0);
4997 offset = (uint64_t)IVAL(req->vwv+3, 0);
4999 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5000 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
5002 br_lck = do_lock(req->sconn->msg_ctx,
5004 (uint64_t)req->smbpid,
5009 False, /* Non-blocking lock. */
5014 TALLOC_FREE(br_lck);
5016 if (NT_STATUS_V(status)) {
5017 reply_nterror(req, status);
5018 END_PROFILE(SMBlock);
5022 reply_outbuf(req, 0, 0);
5024 END_PROFILE(SMBlock);
5028 /****************************************************************************
5030 ****************************************************************************/
5032 void reply_unlock(struct smb_request *req)
5034 connection_struct *conn = req->conn;
5035 uint64_t count,offset;
5039 START_PROFILE(SMBunlock);
5042 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5043 END_PROFILE(SMBunlock);
5047 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5049 if (!check_fsp(conn, req, fsp)) {
5050 END_PROFILE(SMBunlock);
5054 count = (uint64_t)IVAL(req->vwv+1, 0);
5055 offset = (uint64_t)IVAL(req->vwv+3, 0);
5057 status = do_unlock(req->sconn->msg_ctx,
5059 (uint64_t)req->smbpid,
5064 if (NT_STATUS_V(status)) {
5065 reply_nterror(req, status);
5066 END_PROFILE(SMBunlock);
5070 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5071 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5073 reply_outbuf(req, 0, 0);
5075 END_PROFILE(SMBunlock);
5080 #define DBGC_CLASS DBGC_ALL
5082 /****************************************************************************
5084 conn POINTER CAN BE NULL HERE !
5085 ****************************************************************************/
5087 void reply_tdis(struct smb_request *req)
5089 connection_struct *conn = req->conn;
5090 START_PROFILE(SMBtdis);
5093 DEBUG(4,("Invalid connection in tdis\n"));
5094 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5095 END_PROFILE(SMBtdis);
5101 close_cnum(conn,req->vuid);
5104 reply_outbuf(req, 0, 0);
5105 END_PROFILE(SMBtdis);
5109 /****************************************************************************
5111 conn POINTER CAN BE NULL HERE !
5112 ****************************************************************************/
5114 void reply_echo(struct smb_request *req)
5116 connection_struct *conn = req->conn;
5117 struct smb_perfcount_data local_pcd;
5118 struct smb_perfcount_data *cur_pcd;
5122 START_PROFILE(SMBecho);
5124 smb_init_perfcount_data(&local_pcd);
5127 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5128 END_PROFILE(SMBecho);
5132 smb_reverb = SVAL(req->vwv+0, 0);
5134 reply_outbuf(req, 1, req->buflen);
5136 /* copy any incoming data back out */
5137 if (req->buflen > 0) {
5138 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5141 if (smb_reverb > 100) {
5142 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5146 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5148 /* this makes sure we catch the request pcd */
5149 if (seq_num == smb_reverb) {
5150 cur_pcd = &req->pcd;
5152 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5153 cur_pcd = &local_pcd;
5156 SSVAL(req->outbuf,smb_vwv0,seq_num);
5158 show_msg((char *)req->outbuf);
5159 if (!srv_send_smb(req->sconn,
5160 (char *)req->outbuf,
5161 true, req->seqnum+1,
5162 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5164 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5167 DEBUG(3,("echo %d times\n", smb_reverb));
5169 TALLOC_FREE(req->outbuf);
5171 END_PROFILE(SMBecho);
5175 /****************************************************************************
5176 Reply to a printopen.
5177 ****************************************************************************/
5179 void reply_printopen(struct smb_request *req)
5181 connection_struct *conn = req->conn;
5185 START_PROFILE(SMBsplopen);
5188 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5189 END_PROFILE(SMBsplopen);
5193 if (!CAN_PRINT(conn)) {
5194 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5195 END_PROFILE(SMBsplopen);
5199 status = file_new(req, conn, &fsp);
5200 if(!NT_STATUS_IS_OK(status)) {
5201 reply_nterror(req, status);
5202 END_PROFILE(SMBsplopen);
5206 /* Open for exclusive use, write only. */
5207 status = print_spool_open(fsp, NULL, req->vuid);
5209 if (!NT_STATUS_IS_OK(status)) {
5210 file_free(req, fsp);
5211 reply_nterror(req, status);
5212 END_PROFILE(SMBsplopen);
5216 reply_outbuf(req, 1, 0);
5217 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5219 DEBUG(3,("openprint fd=%d fnum=%d\n",
5220 fsp->fh->fd, fsp->fnum));
5222 END_PROFILE(SMBsplopen);
5226 /****************************************************************************
5227 Reply to a printclose.
5228 ****************************************************************************/
5230 void reply_printclose(struct smb_request *req)
5232 connection_struct *conn = req->conn;
5236 START_PROFILE(SMBsplclose);
5239 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5240 END_PROFILE(SMBsplclose);
5244 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5246 if (!check_fsp(conn, req, fsp)) {
5247 END_PROFILE(SMBsplclose);
5251 if (!CAN_PRINT(conn)) {
5252 reply_force_doserror(req, ERRSRV, ERRerror);
5253 END_PROFILE(SMBsplclose);
5257 DEBUG(3,("printclose fd=%d fnum=%d\n",
5258 fsp->fh->fd,fsp->fnum));
5260 status = close_file(req, fsp, NORMAL_CLOSE);
5262 if(!NT_STATUS_IS_OK(status)) {
5263 reply_nterror(req, status);
5264 END_PROFILE(SMBsplclose);
5268 reply_outbuf(req, 0, 0);
5270 END_PROFILE(SMBsplclose);
5274 /****************************************************************************
5275 Reply to a printqueue.
5276 ****************************************************************************/
5278 void reply_printqueue(struct smb_request *req)
5280 connection_struct *conn = req->conn;
5284 START_PROFILE(SMBsplretq);
5287 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5288 END_PROFILE(SMBsplretq);
5292 max_count = SVAL(req->vwv+0, 0);
5293 start_index = SVAL(req->vwv+1, 0);
5295 /* we used to allow the client to get the cnum wrong, but that
5296 is really quite gross and only worked when there was only
5297 one printer - I think we should now only accept it if they
5298 get it right (tridge) */
5299 if (!CAN_PRINT(conn)) {
5300 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5301 END_PROFILE(SMBsplretq);
5305 reply_outbuf(req, 2, 3);
5306 SSVAL(req->outbuf,smb_vwv0,0);
5307 SSVAL(req->outbuf,smb_vwv1,0);
5308 SCVAL(smb_buf(req->outbuf),0,1);
5309 SSVAL(smb_buf(req->outbuf),1,0);
5311 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5312 start_index, max_count));
5315 TALLOC_CTX *mem_ctx = talloc_tos();
5318 const char *sharename = lp_servicename(SNUM(conn));
5319 struct rpc_pipe_client *cli = NULL;
5320 struct dcerpc_binding_handle *b = NULL;
5321 struct policy_handle handle;
5322 struct spoolss_DevmodeContainer devmode_ctr;
5323 union spoolss_JobInfo *info;
5325 uint32_t num_to_get;
5329 ZERO_STRUCT(handle);
5331 status = rpc_pipe_open_interface(conn,
5332 &ndr_table_spoolss.syntax_id,
5334 &conn->sconn->client_id,
5335 conn->sconn->msg_ctx,
5337 if (!NT_STATUS_IS_OK(status)) {
5338 DEBUG(0, ("reply_printqueue: "
5339 "could not connect to spoolss: %s\n",
5340 nt_errstr(status)));
5341 reply_nterror(req, status);
5344 b = cli->binding_handle;
5346 ZERO_STRUCT(devmode_ctr);
5348 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5351 SEC_FLAG_MAXIMUM_ALLOWED,
5354 if (!NT_STATUS_IS_OK(status)) {
5355 reply_nterror(req, status);
5358 if (!W_ERROR_IS_OK(werr)) {
5359 reply_nterror(req, werror_to_ntstatus(werr));
5363 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5371 if (!W_ERROR_IS_OK(werr)) {
5372 reply_nterror(req, werror_to_ntstatus(werr));
5376 if (max_count > 0) {
5377 first = start_index;
5379 first = start_index + max_count + 1;
5382 if (first >= count) {
5385 num_to_get = first + MIN(ABS(max_count), count - first);
5388 for (i = first; i < num_to_get; i++) {
5391 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5393 uint16_t qrapjobid = pjobid_to_rap(sharename,
5394 info[i].info2.job_id);
5396 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5402 srv_put_dos_date2(p, 0, qtime);
5403 SCVAL(p, 4, qstatus);
5404 SSVAL(p, 5, qrapjobid);
5405 SIVAL(p, 7, info[i].info2.size);
5407 srvstr_push(blob, req->flags2, p+12,
5408 info[i].info2.notify_name, 16, STR_ASCII);
5410 if (message_push_blob(
5413 blob, sizeof(blob))) == -1) {
5414 reply_nterror(req, NT_STATUS_NO_MEMORY);
5420 SSVAL(req->outbuf,smb_vwv0,count);
5421 SSVAL(req->outbuf,smb_vwv1,
5422 (max_count>0?first+count:first-1));
5423 SCVAL(smb_buf(req->outbuf),0,1);
5424 SSVAL(smb_buf(req->outbuf),1,28*count);
5428 DEBUG(3, ("%u entries returned in queue\n",
5432 if (b && is_valid_policy_hnd(&handle)) {
5433 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5438 END_PROFILE(SMBsplretq);
5442 /****************************************************************************
5443 Reply to a printwrite.
5444 ****************************************************************************/
5446 void reply_printwrite(struct smb_request *req)
5448 connection_struct *conn = req->conn;
5453 START_PROFILE(SMBsplwr);
5456 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5457 END_PROFILE(SMBsplwr);
5461 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5463 if (!check_fsp(conn, req, fsp)) {
5464 END_PROFILE(SMBsplwr);
5468 if (!fsp->print_file) {
5469 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5470 END_PROFILE(SMBsplwr);
5474 if (!CHECK_WRITE(fsp)) {
5475 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5476 END_PROFILE(SMBsplwr);
5480 numtowrite = SVAL(req->buf, 1);
5482 if (req->buflen < numtowrite + 3) {
5483 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5484 END_PROFILE(SMBsplwr);
5488 data = (const char *)req->buf + 3;
5490 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5491 reply_nterror(req, map_nt_error_from_unix(errno));
5492 END_PROFILE(SMBsplwr);
5496 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5498 END_PROFILE(SMBsplwr);
5502 /****************************************************************************
5504 ****************************************************************************/
5506 void reply_mkdir(struct smb_request *req)
5508 connection_struct *conn = req->conn;
5509 struct smb_filename *smb_dname = NULL;
5510 char *directory = NULL;
5512 TALLOC_CTX *ctx = talloc_tos();
5514 START_PROFILE(SMBmkdir);
5516 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5517 STR_TERMINATE, &status);
5518 if (!NT_STATUS_IS_OK(status)) {
5519 reply_nterror(req, status);
5523 status = filename_convert(ctx, conn,
5524 req->flags2 & FLAGS2_DFS_PATHNAMES,
5529 if (!NT_STATUS_IS_OK(status)) {
5530 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5531 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5532 ERRSRV, ERRbadpath);
5535 reply_nterror(req, status);
5539 status = create_directory(conn, req, smb_dname);
5541 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5543 if (!NT_STATUS_IS_OK(status)) {
5545 if (!use_nt_status()
5546 && NT_STATUS_EQUAL(status,
5547 NT_STATUS_OBJECT_NAME_COLLISION)) {
5549 * Yes, in the DOS error code case we get a
5550 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5551 * samba4 torture test.
5553 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5556 reply_nterror(req, status);
5560 reply_outbuf(req, 0, 0);
5562 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5564 TALLOC_FREE(smb_dname);
5565 END_PROFILE(SMBmkdir);
5569 /****************************************************************************
5571 ****************************************************************************/
5573 void reply_rmdir(struct smb_request *req)
5575 connection_struct *conn = req->conn;
5576 struct smb_filename *smb_dname = NULL;
5577 char *directory = NULL;
5579 TALLOC_CTX *ctx = talloc_tos();
5580 files_struct *fsp = NULL;
5582 struct smbd_server_connection *sconn = req->sconn;
5584 START_PROFILE(SMBrmdir);
5586 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5587 STR_TERMINATE, &status);
5588 if (!NT_STATUS_IS_OK(status)) {
5589 reply_nterror(req, status);
5593 status = filename_convert(ctx, conn,
5594 req->flags2 & FLAGS2_DFS_PATHNAMES,
5599 if (!NT_STATUS_IS_OK(status)) {
5600 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5601 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5602 ERRSRV, ERRbadpath);
5605 reply_nterror(req, status);
5609 if (is_ntfs_stream_smb_fname(smb_dname)) {
5610 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5614 status = SMB_VFS_CREATE_FILE(
5617 0, /* root_dir_fid */
5618 smb_dname, /* fname */
5619 DELETE_ACCESS, /* access_mask */
5620 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5622 FILE_OPEN, /* create_disposition*/
5623 FILE_DIRECTORY_FILE, /* create_options */
5624 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5625 0, /* oplock_request */
5626 0, /* allocation_size */
5627 0, /* private_flags */
5633 if (!NT_STATUS_IS_OK(status)) {
5634 if (open_was_deferred(req->mid)) {
5635 /* We have re-scheduled this call. */
5638 reply_nterror(req, status);
5642 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5643 if (!NT_STATUS_IS_OK(status)) {
5644 close_file(req, fsp, ERROR_CLOSE);
5645 reply_nterror(req, status);
5649 if (!set_delete_on_close(fsp, true, &conn->session_info->utok)) {
5650 close_file(req, fsp, ERROR_CLOSE);
5651 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5655 status = close_file(req, fsp, NORMAL_CLOSE);
5656 if (!NT_STATUS_IS_OK(status)) {
5657 reply_nterror(req, status);
5659 reply_outbuf(req, 0, 0);
5662 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5664 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5666 TALLOC_FREE(smb_dname);
5667 END_PROFILE(SMBrmdir);
5671 /*******************************************************************
5672 Resolve wildcards in a filename rename.
5673 ********************************************************************/
5675 static bool resolve_wildcards(TALLOC_CTX *ctx,
5680 char *name2_copy = NULL;
5685 char *p,*p2, *pname1, *pname2;
5687 name2_copy = talloc_strdup(ctx, name2);
5692 pname1 = strrchr_m(name1,'/');
5693 pname2 = strrchr_m(name2_copy,'/');
5695 if (!pname1 || !pname2) {
5699 /* Truncate the copy of name2 at the last '/' */
5702 /* Now go past the '/' */
5706 root1 = talloc_strdup(ctx, pname1);
5707 root2 = talloc_strdup(ctx, pname2);
5709 if (!root1 || !root2) {
5713 p = strrchr_m(root1,'.');
5716 ext1 = talloc_strdup(ctx, p+1);
5718 ext1 = talloc_strdup(ctx, "");
5720 p = strrchr_m(root2,'.');
5723 ext2 = talloc_strdup(ctx, p+1);
5725 ext2 = talloc_strdup(ctx, "");
5728 if (!ext1 || !ext2) {
5736 /* Hmmm. Should this be mb-aware ? */
5739 } else if (*p2 == '*') {
5741 root2 = talloc_asprintf(ctx, "%s%s",
5760 /* Hmmm. Should this be mb-aware ? */
5763 } else if (*p2 == '*') {
5765 ext2 = talloc_asprintf(ctx, "%s%s",
5781 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5786 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5798 /****************************************************************************
5799 Ensure open files have their names updated. Updated to notify other smbd's
5801 ****************************************************************************/
5803 static void rename_open_files(connection_struct *conn,
5804 struct share_mode_lock *lck,
5805 uint32_t orig_name_hash,
5806 const struct smb_filename *smb_fname_dst)
5809 bool did_rename = False;
5811 uint32_t new_name_hash;
5813 for(fsp = file_find_di_first(conn->sconn, lck->id); fsp;
5814 fsp = file_find_di_next(fsp)) {
5815 /* fsp_name is a relative path under the fsp. To change this for other
5816 sharepaths we need to manipulate relative paths. */
5817 /* TODO - create the absolute path and manipulate the newname
5818 relative to the sharepath. */
5819 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5822 if (fsp->name_hash != orig_name_hash) {
5825 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5826 "(file_id %s) from %s -> %s\n", fsp->fnum,
5827 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5828 smb_fname_str_dbg(smb_fname_dst)));
5830 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5831 if (NT_STATUS_IS_OK(status)) {
5833 new_name_hash = fsp->name_hash;
5838 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5839 "for %s\n", file_id_string_tos(&lck->id),
5840 smb_fname_str_dbg(smb_fname_dst)));
5843 /* Send messages to all smbd's (not ourself) that the name has changed. */
5844 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5845 orig_name_hash, new_name_hash,
5850 /****************************************************************************
5851 We need to check if the source path is a parent directory of the destination
5852 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5853 refuse the rename with a sharing violation. Under UNIX the above call can
5854 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5855 probably need to check that the client is a Windows one before disallowing
5856 this as a UNIX client (one with UNIX extensions) can know the source is a
5857 symlink and make this decision intelligently. Found by an excellent bug
5858 report from <AndyLiebman@aol.com>.
5859 ****************************************************************************/
5861 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5862 const struct smb_filename *smb_fname_dst)
5864 const char *psrc = smb_fname_src->base_name;
5865 const char *pdst = smb_fname_dst->base_name;
5868 if (psrc[0] == '.' && psrc[1] == '/') {
5871 if (pdst[0] == '.' && pdst[1] == '/') {
5874 if ((slen = strlen(psrc)) > strlen(pdst)) {
5877 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5881 * Do the notify calls from a rename
5884 static void notify_rename(connection_struct *conn, bool is_dir,
5885 const struct smb_filename *smb_fname_src,
5886 const struct smb_filename *smb_fname_dst)
5888 char *parent_dir_src = NULL;
5889 char *parent_dir_dst = NULL;
5892 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5893 : FILE_NOTIFY_CHANGE_FILE_NAME;
5895 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5896 &parent_dir_src, NULL) ||
5897 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5898 &parent_dir_dst, NULL)) {
5902 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5903 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5904 smb_fname_src->base_name);
5905 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5906 smb_fname_dst->base_name);
5909 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5910 smb_fname_src->base_name);
5911 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5912 smb_fname_dst->base_name);
5915 /* this is a strange one. w2k3 gives an additional event for
5916 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5917 files, but not directories */
5919 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5920 FILE_NOTIFY_CHANGE_ATTRIBUTES
5921 |FILE_NOTIFY_CHANGE_CREATION,
5922 smb_fname_dst->base_name);
5925 TALLOC_FREE(parent_dir_src);
5926 TALLOC_FREE(parent_dir_dst);
5929 /****************************************************************************
5930 Rename an open file - given an fsp.
5931 ****************************************************************************/
5933 NTSTATUS rename_internals_fsp(connection_struct *conn,
5935 const struct smb_filename *smb_fname_dst_in,
5937 bool replace_if_exists)
5939 TALLOC_CTX *ctx = talloc_tos();
5940 struct smb_filename *smb_fname_dst = NULL;
5941 NTSTATUS status = NT_STATUS_OK;
5942 struct share_mode_lock *lck = NULL;
5943 bool dst_exists, old_is_stream, new_is_stream;
5945 status = check_name(conn, smb_fname_dst_in->base_name);
5946 if (!NT_STATUS_IS_OK(status)) {
5950 /* Make a copy of the dst smb_fname structs */
5952 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5953 if (!NT_STATUS_IS_OK(status)) {
5958 * Check for special case with case preserving and not
5959 * case sensitive. If the old last component differs from the original
5960 * last component only by case, then we should allow
5961 * the rename (user is trying to change the case of the
5964 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5965 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5966 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5968 char *fname_dst_lcomp_base_mod = NULL;
5969 struct smb_filename *smb_fname_orig_lcomp = NULL;
5972 * Get the last component of the destination name.
5974 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5976 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5978 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
5980 if (!fname_dst_lcomp_base_mod) {
5981 status = NT_STATUS_NO_MEMORY;
5986 * Create an smb_filename struct using the original last
5987 * component of the destination.
5989 status = create_synthetic_smb_fname_split(ctx,
5990 smb_fname_dst->original_lcomp, NULL,
5991 &smb_fname_orig_lcomp);
5992 if (!NT_STATUS_IS_OK(status)) {
5993 TALLOC_FREE(fname_dst_lcomp_base_mod);
5997 /* If the base names only differ by case, use original. */
5998 if(!strcsequal(fname_dst_lcomp_base_mod,
5999 smb_fname_orig_lcomp->base_name)) {
6002 * Replace the modified last component with the
6006 *last_slash = '\0'; /* Truncate at the '/' */
6007 tmp = talloc_asprintf(smb_fname_dst,
6009 smb_fname_dst->base_name,
6010 smb_fname_orig_lcomp->base_name);
6012 tmp = talloc_asprintf(smb_fname_dst,
6014 smb_fname_orig_lcomp->base_name);
6017 status = NT_STATUS_NO_MEMORY;
6018 TALLOC_FREE(fname_dst_lcomp_base_mod);
6019 TALLOC_FREE(smb_fname_orig_lcomp);
6022 TALLOC_FREE(smb_fname_dst->base_name);
6023 smb_fname_dst->base_name = tmp;
6026 /* If the stream_names only differ by case, use original. */
6027 if(!strcsequal(smb_fname_dst->stream_name,
6028 smb_fname_orig_lcomp->stream_name)) {
6030 /* Use the original stream. */
6031 tmp = talloc_strdup(smb_fname_dst,
6032 smb_fname_orig_lcomp->stream_name);
6034 status = NT_STATUS_NO_MEMORY;
6035 TALLOC_FREE(fname_dst_lcomp_base_mod);
6036 TALLOC_FREE(smb_fname_orig_lcomp);
6039 TALLOC_FREE(smb_fname_dst->stream_name);
6040 smb_fname_dst->stream_name = tmp;
6042 TALLOC_FREE(fname_dst_lcomp_base_mod);
6043 TALLOC_FREE(smb_fname_orig_lcomp);
6047 * If the src and dest names are identical - including case,
6048 * don't do the rename, just return success.
6051 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6052 strcsequal(fsp->fsp_name->stream_name,
6053 smb_fname_dst->stream_name)) {
6054 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6055 "- returning success\n",
6056 smb_fname_str_dbg(smb_fname_dst)));
6057 status = NT_STATUS_OK;
6061 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6062 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6064 /* Return the correct error code if both names aren't streams. */
6065 if (!old_is_stream && new_is_stream) {
6066 status = NT_STATUS_OBJECT_NAME_INVALID;
6070 if (old_is_stream && !new_is_stream) {
6071 status = NT_STATUS_INVALID_PARAMETER;
6075 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6077 if(!replace_if_exists && dst_exists) {
6078 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6079 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6080 smb_fname_str_dbg(smb_fname_dst)));
6081 status = NT_STATUS_OBJECT_NAME_COLLISION;
6086 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6087 &smb_fname_dst->st);
6088 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6090 /* The file can be open when renaming a stream */
6091 if (dst_fsp && !new_is_stream) {
6092 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6093 status = NT_STATUS_ACCESS_DENIED;
6098 /* Ensure we have a valid stat struct for the source. */
6099 status = vfs_stat_fsp(fsp);
6100 if (!NT_STATUS_IS_OK(status)) {
6104 status = can_rename(conn, fsp, attrs);
6106 if (!NT_STATUS_IS_OK(status)) {
6107 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6108 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6109 smb_fname_str_dbg(smb_fname_dst)));
6110 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6111 status = NT_STATUS_ACCESS_DENIED;
6115 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6116 status = NT_STATUS_ACCESS_DENIED;
6119 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6123 * We have the file open ourselves, so not being able to get the
6124 * corresponding share mode lock is a fatal error.
6127 SMB_ASSERT(lck != NULL);
6129 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6130 uint32 create_options = fsp->fh->private_options;
6132 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6133 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6134 smb_fname_str_dbg(smb_fname_dst)));
6136 if (!lp_posix_pathnames() &&
6137 (lp_map_archive(SNUM(conn)) ||
6138 lp_store_dos_attributes(SNUM(conn)))) {
6139 /* We must set the archive bit on the newly
6141 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6142 uint32_t old_dosmode = dos_mode(conn,
6144 file_set_dosmode(conn,
6146 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6152 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6155 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6158 * A rename acts as a new file create w.r.t. allowing an initial delete
6159 * on close, probably because in Windows there is a new handle to the
6160 * new file. If initial delete on close was requested but not
6161 * originally set, we need to set it here. This is probably not 100% correct,
6162 * but will work for the CIFSFS client which in non-posix mode
6163 * depends on these semantics. JRA.
6166 if (create_options & FILE_DELETE_ON_CLOSE) {
6167 status = can_set_delete_on_close(fsp, 0);
6169 if (NT_STATUS_IS_OK(status)) {
6170 /* Note that here we set the *inital* delete on close flag,
6171 * not the regular one. The magic gets handled in close. */
6172 fsp->initial_delete_on_close = True;
6176 status = NT_STATUS_OK;
6182 if (errno == ENOTDIR || errno == EISDIR) {
6183 status = NT_STATUS_OBJECT_NAME_COLLISION;
6185 status = map_nt_error_from_unix(errno);
6188 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6189 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6190 smb_fname_str_dbg(smb_fname_dst)));
6193 TALLOC_FREE(smb_fname_dst);
6198 /****************************************************************************
6199 The guts of the rename command, split out so it may be called by the NT SMB
6201 ****************************************************************************/
6203 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6204 connection_struct *conn,
6205 struct smb_request *req,
6206 struct smb_filename *smb_fname_src,
6207 struct smb_filename *smb_fname_dst,
6209 bool replace_if_exists,
6212 uint32_t access_mask)
6214 char *fname_src_dir = NULL;
6215 char *fname_src_mask = NULL;
6217 NTSTATUS status = NT_STATUS_OK;
6218 struct smb_Dir *dir_hnd = NULL;
6219 const char *dname = NULL;
6220 char *talloced = NULL;
6222 int create_options = 0;
6223 bool posix_pathnames = lp_posix_pathnames();
6226 * Split the old name into directory and last component
6227 * strings. Note that unix_convert may have stripped off a
6228 * leading ./ from both name and newname if the rename is
6229 * at the root of the share. We need to make sure either both
6230 * name and newname contain a / character or neither of them do
6231 * as this is checked in resolve_wildcards().
6234 /* Split up the directory from the filename/mask. */
6235 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6236 &fname_src_dir, &fname_src_mask);
6237 if (!NT_STATUS_IS_OK(status)) {
6238 status = NT_STATUS_NO_MEMORY;
6243 * We should only check the mangled cache
6244 * here if unix_convert failed. This means
6245 * that the path in 'mask' doesn't exist
6246 * on the file system and so we need to look
6247 * for a possible mangle. This patch from
6248 * Tine Smukavec <valentin.smukavec@hermes.si>.
6251 if (!VALID_STAT(smb_fname_src->st) &&
6252 mangle_is_mangled(fname_src_mask, conn->params)) {
6253 char *new_mask = NULL;
6254 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6257 TALLOC_FREE(fname_src_mask);
6258 fname_src_mask = new_mask;
6262 if (!src_has_wild) {
6266 * Only one file needs to be renamed. Append the mask back
6267 * onto the directory.
6269 TALLOC_FREE(smb_fname_src->base_name);
6270 if (ISDOT(fname_src_dir)) {
6271 /* Ensure we use canonical names on open. */
6272 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6276 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6281 if (!smb_fname_src->base_name) {
6282 status = NT_STATUS_NO_MEMORY;
6286 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6287 "case_preserve = %d, short case preserve = %d, "
6288 "directory = %s, newname = %s, "
6289 "last_component_dest = %s\n",
6290 conn->case_sensitive, conn->case_preserve,
6291 conn->short_case_preserve,
6292 smb_fname_str_dbg(smb_fname_src),
6293 smb_fname_str_dbg(smb_fname_dst),
6294 smb_fname_dst->original_lcomp));
6296 /* The dest name still may have wildcards. */
6297 if (dest_has_wild) {
6298 char *fname_dst_mod = NULL;
6299 if (!resolve_wildcards(smb_fname_dst,
6300 smb_fname_src->base_name,
6301 smb_fname_dst->base_name,
6303 DEBUG(6, ("rename_internals: resolve_wildcards "
6305 smb_fname_src->base_name,
6306 smb_fname_dst->base_name));
6307 status = NT_STATUS_NO_MEMORY;
6310 TALLOC_FREE(smb_fname_dst->base_name);
6311 smb_fname_dst->base_name = fname_dst_mod;
6314 ZERO_STRUCT(smb_fname_src->st);
6315 if (posix_pathnames) {
6316 SMB_VFS_LSTAT(conn, smb_fname_src);
6318 SMB_VFS_STAT(conn, smb_fname_src);
6321 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6322 create_options |= FILE_DIRECTORY_FILE;
6325 status = SMB_VFS_CREATE_FILE(
6328 0, /* root_dir_fid */
6329 smb_fname_src, /* fname */
6330 access_mask, /* access_mask */
6331 (FILE_SHARE_READ | /* share_access */
6333 FILE_OPEN, /* create_disposition*/
6334 create_options, /* create_options */
6335 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6336 0, /* oplock_request */
6337 0, /* allocation_size */
6338 0, /* private_flags */
6344 if (!NT_STATUS_IS_OK(status)) {
6345 DEBUG(3, ("Could not open rename source %s: %s\n",
6346 smb_fname_str_dbg(smb_fname_src),
6347 nt_errstr(status)));
6351 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6352 attrs, replace_if_exists);
6354 close_file(req, fsp, NORMAL_CLOSE);
6356 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6357 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6358 smb_fname_str_dbg(smb_fname_dst)));
6364 * Wildcards - process each file that matches.
6366 if (strequal(fname_src_mask, "????????.???")) {
6367 TALLOC_FREE(fname_src_mask);
6368 fname_src_mask = talloc_strdup(ctx, "*");
6369 if (!fname_src_mask) {
6370 status = NT_STATUS_NO_MEMORY;
6375 status = check_name(conn, fname_src_dir);
6376 if (!NT_STATUS_IS_OK(status)) {
6380 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6382 if (dir_hnd == NULL) {
6383 status = map_nt_error_from_unix(errno);
6387 status = NT_STATUS_NO_SUCH_FILE;
6389 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6390 * - gentest fix. JRA
6393 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6395 files_struct *fsp = NULL;
6396 char *destname = NULL;
6397 bool sysdir_entry = False;
6399 /* Quick check for "." and ".." */
6400 if (ISDOT(dname) || ISDOTDOT(dname)) {
6402 sysdir_entry = True;
6404 TALLOC_FREE(talloced);
6409 if (!is_visible_file(conn, fname_src_dir, dname,
6410 &smb_fname_src->st, false)) {
6411 TALLOC_FREE(talloced);
6415 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6416 TALLOC_FREE(talloced);
6421 status = NT_STATUS_OBJECT_NAME_INVALID;
6425 TALLOC_FREE(smb_fname_src->base_name);
6426 if (ISDOT(fname_src_dir)) {
6427 /* Ensure we use canonical names on open. */
6428 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6432 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6437 if (!smb_fname_src->base_name) {
6438 status = NT_STATUS_NO_MEMORY;
6442 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6443 smb_fname_dst->base_name,
6445 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6446 smb_fname_src->base_name, destname));
6447 TALLOC_FREE(talloced);
6451 status = NT_STATUS_NO_MEMORY;
6455 TALLOC_FREE(smb_fname_dst->base_name);
6456 smb_fname_dst->base_name = destname;
6458 ZERO_STRUCT(smb_fname_src->st);
6459 if (posix_pathnames) {
6460 SMB_VFS_LSTAT(conn, smb_fname_src);
6462 SMB_VFS_STAT(conn, smb_fname_src);
6467 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6468 create_options |= FILE_DIRECTORY_FILE;
6471 status = SMB_VFS_CREATE_FILE(
6474 0, /* root_dir_fid */
6475 smb_fname_src, /* fname */
6476 access_mask, /* access_mask */
6477 (FILE_SHARE_READ | /* share_access */
6479 FILE_OPEN, /* create_disposition*/
6480 create_options, /* create_options */
6481 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6482 0, /* oplock_request */
6483 0, /* allocation_size */
6484 0, /* private_flags */
6490 if (!NT_STATUS_IS_OK(status)) {
6491 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6492 "returned %s rename %s -> %s\n",
6494 smb_fname_str_dbg(smb_fname_src),
6495 smb_fname_str_dbg(smb_fname_dst)));
6499 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6501 if (!smb_fname_dst->original_lcomp) {
6502 status = NT_STATUS_NO_MEMORY;
6506 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6507 attrs, replace_if_exists);
6509 close_file(req, fsp, NORMAL_CLOSE);
6511 if (!NT_STATUS_IS_OK(status)) {
6512 DEBUG(3, ("rename_internals_fsp returned %s for "
6513 "rename %s -> %s\n", nt_errstr(status),
6514 smb_fname_str_dbg(smb_fname_src),
6515 smb_fname_str_dbg(smb_fname_dst)));
6521 DEBUG(3,("rename_internals: doing rename on %s -> "
6522 "%s\n", smb_fname_str_dbg(smb_fname_src),
6523 smb_fname_str_dbg(smb_fname_src)));
6524 TALLOC_FREE(talloced);
6526 TALLOC_FREE(dir_hnd);
6528 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6529 status = map_nt_error_from_unix(errno);
6533 TALLOC_FREE(talloced);
6534 TALLOC_FREE(fname_src_dir);
6535 TALLOC_FREE(fname_src_mask);
6539 /****************************************************************************
6541 ****************************************************************************/
6543 void reply_mv(struct smb_request *req)
6545 connection_struct *conn = req->conn;
6547 char *newname = NULL;
6551 bool src_has_wcard = False;
6552 bool dest_has_wcard = False;
6553 TALLOC_CTX *ctx = talloc_tos();
6554 struct smb_filename *smb_fname_src = NULL;
6555 struct smb_filename *smb_fname_dst = NULL;
6556 bool stream_rename = false;
6558 START_PROFILE(SMBmv);
6561 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6565 attrs = SVAL(req->vwv+0, 0);
6567 p = (const char *)req->buf + 1;
6568 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6569 &status, &src_has_wcard);
6570 if (!NT_STATUS_IS_OK(status)) {
6571 reply_nterror(req, status);
6575 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6576 &status, &dest_has_wcard);
6577 if (!NT_STATUS_IS_OK(status)) {
6578 reply_nterror(req, status);
6582 if (!lp_posix_pathnames()) {
6583 /* The newname must begin with a ':' if the
6584 name contains a ':'. */
6585 if (strchr_m(name, ':')) {
6586 if (newname[0] != ':') {
6587 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6590 stream_rename = true;
6594 status = filename_convert(ctx,
6596 req->flags2 & FLAGS2_DFS_PATHNAMES,
6598 UCF_COND_ALLOW_WCARD_LCOMP,
6602 if (!NT_STATUS_IS_OK(status)) {
6603 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6604 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6605 ERRSRV, ERRbadpath);
6608 reply_nterror(req, status);
6612 status = filename_convert(ctx,
6614 req->flags2 & FLAGS2_DFS_PATHNAMES,
6616 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6620 if (!NT_STATUS_IS_OK(status)) {
6621 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6622 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6623 ERRSRV, ERRbadpath);
6626 reply_nterror(req, status);
6630 if (stream_rename) {
6631 /* smb_fname_dst->base_name must be the same as
6632 smb_fname_src->base_name. */
6633 TALLOC_FREE(smb_fname_dst->base_name);
6634 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6635 smb_fname_src->base_name);
6636 if (!smb_fname_dst->base_name) {
6637 reply_nterror(req, NT_STATUS_NO_MEMORY);
6642 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6643 smb_fname_str_dbg(smb_fname_dst)));
6645 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6646 attrs, False, src_has_wcard, dest_has_wcard,
6648 if (!NT_STATUS_IS_OK(status)) {
6649 if (open_was_deferred(req->mid)) {
6650 /* We have re-scheduled this call. */
6653 reply_nterror(req, status);
6657 reply_outbuf(req, 0, 0);
6659 TALLOC_FREE(smb_fname_src);
6660 TALLOC_FREE(smb_fname_dst);
6665 /*******************************************************************
6666 Copy a file as part of a reply_copy.
6667 ******************************************************************/
6670 * TODO: check error codes on all callers
6673 NTSTATUS copy_file(TALLOC_CTX *ctx,
6674 connection_struct *conn,
6675 struct smb_filename *smb_fname_src,
6676 struct smb_filename *smb_fname_dst,
6679 bool target_is_directory)
6681 struct smb_filename *smb_fname_dst_tmp = NULL;
6683 files_struct *fsp1,*fsp2;
6685 uint32 new_create_disposition;
6689 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6690 if (!NT_STATUS_IS_OK(status)) {
6695 * If the target is a directory, extract the last component from the
6696 * src filename and append it to the dst filename
6698 if (target_is_directory) {
6701 /* dest/target can't be a stream if it's a directory. */
6702 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6704 p = strrchr_m(smb_fname_src->base_name,'/');
6708 p = smb_fname_src->base_name;
6710 smb_fname_dst_tmp->base_name =
6711 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6713 if (!smb_fname_dst_tmp->base_name) {
6714 status = NT_STATUS_NO_MEMORY;
6719 status = vfs_file_exist(conn, smb_fname_src);
6720 if (!NT_STATUS_IS_OK(status)) {
6724 if (!target_is_directory && count) {
6725 new_create_disposition = FILE_OPEN;
6727 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6729 &new_create_disposition,
6732 status = NT_STATUS_INVALID_PARAMETER;
6737 /* Open the src file for reading. */
6738 status = SMB_VFS_CREATE_FILE(
6741 0, /* root_dir_fid */
6742 smb_fname_src, /* fname */
6743 FILE_GENERIC_READ, /* access_mask */
6744 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6745 FILE_OPEN, /* create_disposition*/
6746 0, /* create_options */
6747 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6748 INTERNAL_OPEN_ONLY, /* oplock_request */
6749 0, /* allocation_size */
6750 0, /* private_flags */
6756 if (!NT_STATUS_IS_OK(status)) {
6760 dosattrs = dos_mode(conn, smb_fname_src);
6762 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6763 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6766 /* Open the dst file for writing. */
6767 status = SMB_VFS_CREATE_FILE(
6770 0, /* root_dir_fid */
6771 smb_fname_dst, /* fname */
6772 FILE_GENERIC_WRITE, /* access_mask */
6773 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6774 new_create_disposition, /* create_disposition*/
6775 0, /* create_options */
6776 dosattrs, /* file_attributes */
6777 INTERNAL_OPEN_ONLY, /* oplock_request */
6778 0, /* allocation_size */
6779 0, /* private_flags */
6785 if (!NT_STATUS_IS_OK(status)) {
6786 close_file(NULL, fsp1, ERROR_CLOSE);
6790 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6791 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6793 DEBUG(0, ("error - vfs lseek returned error %s\n",
6795 status = map_nt_error_from_unix(errno);
6796 close_file(NULL, fsp1, ERROR_CLOSE);
6797 close_file(NULL, fsp2, ERROR_CLOSE);
6802 /* Do the actual copy. */
6803 if (smb_fname_src->st.st_ex_size) {
6804 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6809 close_file(NULL, fsp1, NORMAL_CLOSE);
6811 /* Ensure the modtime is set correctly on the destination file. */
6812 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6815 * As we are opening fsp1 read-only we only expect
6816 * an error on close on fsp2 if we are out of space.
6817 * Thus we don't look at the error return from the
6820 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6822 if (!NT_STATUS_IS_OK(status)) {
6826 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6827 status = NT_STATUS_DISK_FULL;
6831 status = NT_STATUS_OK;
6834 TALLOC_FREE(smb_fname_dst_tmp);
6838 /****************************************************************************
6839 Reply to a file copy.
6840 ****************************************************************************/
6842 void reply_copy(struct smb_request *req)
6844 connection_struct *conn = req->conn;
6845 struct smb_filename *smb_fname_src = NULL;
6846 struct smb_filename *smb_fname_dst = NULL;
6847 char *fname_src = NULL;
6848 char *fname_dst = NULL;
6849 char *fname_src_mask = NULL;
6850 char *fname_src_dir = NULL;
6853 int error = ERRnoaccess;
6857 bool target_is_directory=False;
6858 bool source_has_wild = False;
6859 bool dest_has_wild = False;
6861 TALLOC_CTX *ctx = talloc_tos();
6863 START_PROFILE(SMBcopy);
6866 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6870 tid2 = SVAL(req->vwv+0, 0);
6871 ofun = SVAL(req->vwv+1, 0);
6872 flags = SVAL(req->vwv+2, 0);
6874 p = (const char *)req->buf;
6875 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6876 &status, &source_has_wild);
6877 if (!NT_STATUS_IS_OK(status)) {
6878 reply_nterror(req, status);
6881 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6882 &status, &dest_has_wild);
6883 if (!NT_STATUS_IS_OK(status)) {
6884 reply_nterror(req, status);
6888 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6890 if (tid2 != conn->cnum) {
6891 /* can't currently handle inter share copies XXXX */
6892 DEBUG(3,("Rejecting inter-share copy\n"));
6893 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6897 status = filename_convert(ctx, conn,
6898 req->flags2 & FLAGS2_DFS_PATHNAMES,
6900 UCF_COND_ALLOW_WCARD_LCOMP,
6903 if (!NT_STATUS_IS_OK(status)) {
6904 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6905 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6906 ERRSRV, ERRbadpath);
6909 reply_nterror(req, status);
6913 status = filename_convert(ctx, conn,
6914 req->flags2 & FLAGS2_DFS_PATHNAMES,
6916 UCF_COND_ALLOW_WCARD_LCOMP,
6919 if (!NT_STATUS_IS_OK(status)) {
6920 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6921 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6922 ERRSRV, ERRbadpath);
6925 reply_nterror(req, status);
6929 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6931 if ((flags&1) && target_is_directory) {
6932 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6936 if ((flags&2) && !target_is_directory) {
6937 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6941 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6942 /* wants a tree copy! XXXX */
6943 DEBUG(3,("Rejecting tree copy\n"));
6944 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6948 /* Split up the directory from the filename/mask. */
6949 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6950 &fname_src_dir, &fname_src_mask);
6951 if (!NT_STATUS_IS_OK(status)) {
6952 reply_nterror(req, NT_STATUS_NO_MEMORY);
6957 * We should only check the mangled cache
6958 * here if unix_convert failed. This means
6959 * that the path in 'mask' doesn't exist
6960 * on the file system and so we need to look
6961 * for a possible mangle. This patch from
6962 * Tine Smukavec <valentin.smukavec@hermes.si>.
6964 if (!VALID_STAT(smb_fname_src->st) &&
6965 mangle_is_mangled(fname_src_mask, conn->params)) {
6966 char *new_mask = NULL;
6967 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6968 &new_mask, conn->params);
6970 /* Use demangled name if one was successfully found. */
6972 TALLOC_FREE(fname_src_mask);
6973 fname_src_mask = new_mask;
6977 if (!source_has_wild) {
6980 * Only one file needs to be copied. Append the mask back onto
6983 TALLOC_FREE(smb_fname_src->base_name);
6984 if (ISDOT(fname_src_dir)) {
6985 /* Ensure we use canonical names on open. */
6986 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6990 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6995 if (!smb_fname_src->base_name) {
6996 reply_nterror(req, NT_STATUS_NO_MEMORY);
7000 if (dest_has_wild) {
7001 char *fname_dst_mod = NULL;
7002 if (!resolve_wildcards(smb_fname_dst,
7003 smb_fname_src->base_name,
7004 smb_fname_dst->base_name,
7006 reply_nterror(req, NT_STATUS_NO_MEMORY);
7009 TALLOC_FREE(smb_fname_dst->base_name);
7010 smb_fname_dst->base_name = fname_dst_mod;
7013 status = check_name(conn, smb_fname_src->base_name);
7014 if (!NT_STATUS_IS_OK(status)) {
7015 reply_nterror(req, status);
7019 status = check_name(conn, smb_fname_dst->base_name);
7020 if (!NT_STATUS_IS_OK(status)) {
7021 reply_nterror(req, status);
7025 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7026 ofun, count, target_is_directory);
7028 if(!NT_STATUS_IS_OK(status)) {
7029 reply_nterror(req, status);
7035 struct smb_Dir *dir_hnd = NULL;
7036 const char *dname = NULL;
7037 char *talloced = NULL;
7041 * There is a wildcard that requires us to actually read the
7042 * src dir and copy each file matching the mask to the dst.
7043 * Right now streams won't be copied, but this could
7044 * presumably be added with a nested loop for reach dir entry.
7046 SMB_ASSERT(!smb_fname_src->stream_name);
7047 SMB_ASSERT(!smb_fname_dst->stream_name);
7049 smb_fname_src->stream_name = NULL;
7050 smb_fname_dst->stream_name = NULL;
7052 if (strequal(fname_src_mask,"????????.???")) {
7053 TALLOC_FREE(fname_src_mask);
7054 fname_src_mask = talloc_strdup(ctx, "*");
7055 if (!fname_src_mask) {
7056 reply_nterror(req, NT_STATUS_NO_MEMORY);
7061 status = check_name(conn, fname_src_dir);
7062 if (!NT_STATUS_IS_OK(status)) {
7063 reply_nterror(req, status);
7067 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7068 if (dir_hnd == NULL) {
7069 status = map_nt_error_from_unix(errno);
7070 reply_nterror(req, status);
7076 /* Iterate over the src dir copying each entry to the dst. */
7077 while ((dname = ReadDirName(dir_hnd, &offset,
7078 &smb_fname_src->st, &talloced))) {
7079 char *destname = NULL;
7081 if (ISDOT(dname) || ISDOTDOT(dname)) {
7082 TALLOC_FREE(talloced);
7086 if (!is_visible_file(conn, fname_src_dir, dname,
7087 &smb_fname_src->st, false)) {
7088 TALLOC_FREE(talloced);
7092 if(!mask_match(dname, fname_src_mask,
7093 conn->case_sensitive)) {
7094 TALLOC_FREE(talloced);
7098 error = ERRnoaccess;
7100 /* Get the src smb_fname struct setup. */
7101 TALLOC_FREE(smb_fname_src->base_name);
7102 if (ISDOT(fname_src_dir)) {
7103 /* Ensure we use canonical names on open. */
7104 smb_fname_src->base_name =
7105 talloc_asprintf(smb_fname_src, "%s",
7108 smb_fname_src->base_name =
7109 talloc_asprintf(smb_fname_src, "%s/%s",
7110 fname_src_dir, dname);
7113 if (!smb_fname_src->base_name) {
7114 TALLOC_FREE(dir_hnd);
7115 TALLOC_FREE(talloced);
7116 reply_nterror(req, NT_STATUS_NO_MEMORY);
7120 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7121 smb_fname_dst->base_name,
7123 TALLOC_FREE(talloced);
7127 TALLOC_FREE(dir_hnd);
7128 TALLOC_FREE(talloced);
7129 reply_nterror(req, NT_STATUS_NO_MEMORY);
7133 TALLOC_FREE(smb_fname_dst->base_name);
7134 smb_fname_dst->base_name = destname;
7136 status = check_name(conn, smb_fname_src->base_name);
7137 if (!NT_STATUS_IS_OK(status)) {
7138 TALLOC_FREE(dir_hnd);
7139 TALLOC_FREE(talloced);
7140 reply_nterror(req, status);
7144 status = check_name(conn, smb_fname_dst->base_name);
7145 if (!NT_STATUS_IS_OK(status)) {
7146 TALLOC_FREE(dir_hnd);
7147 TALLOC_FREE(talloced);
7148 reply_nterror(req, status);
7152 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7153 smb_fname_src->base_name,
7154 smb_fname_dst->base_name));
7156 status = copy_file(ctx, conn, smb_fname_src,
7157 smb_fname_dst, ofun, count,
7158 target_is_directory);
7159 if (NT_STATUS_IS_OK(status)) {
7163 TALLOC_FREE(talloced);
7165 TALLOC_FREE(dir_hnd);
7169 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7173 reply_outbuf(req, 1, 0);
7174 SSVAL(req->outbuf,smb_vwv0,count);
7176 TALLOC_FREE(smb_fname_src);
7177 TALLOC_FREE(smb_fname_dst);
7178 TALLOC_FREE(fname_src);
7179 TALLOC_FREE(fname_dst);
7180 TALLOC_FREE(fname_src_mask);
7181 TALLOC_FREE(fname_src_dir);
7183 END_PROFILE(SMBcopy);
7188 #define DBGC_CLASS DBGC_LOCKING
7190 /****************************************************************************
7191 Get a lock pid, dealing with large count requests.
7192 ****************************************************************************/
7194 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7195 bool large_file_format)
7197 if(!large_file_format)
7198 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7200 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7203 /****************************************************************************
7204 Get a lock count, dealing with large count requests.
7205 ****************************************************************************/
7207 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7208 bool large_file_format)
7212 if(!large_file_format) {
7213 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7216 #if defined(HAVE_LONGLONG)
7217 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7218 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7219 #else /* HAVE_LONGLONG */
7222 * NT4.x seems to be broken in that it sends large file (64 bit)
7223 * lockingX calls even if the CAP_LARGE_FILES was *not*
7224 * negotiated. For boxes without large unsigned ints truncate the
7225 * lock count by dropping the top 32 bits.
7228 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7229 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7230 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7231 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7232 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7235 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7236 #endif /* HAVE_LONGLONG */
7242 #if !defined(HAVE_LONGLONG)
7243 /****************************************************************************
7244 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7245 ****************************************************************************/
7247 static uint32 map_lock_offset(uint32 high, uint32 low)
7251 uint32 highcopy = high;
7254 * Try and find out how many significant bits there are in high.
7257 for(i = 0; highcopy; i++)
7261 * We use 31 bits not 32 here as POSIX
7262 * lock offsets may not be negative.
7265 mask = (~0) << (31 - i);
7268 return 0; /* Fail. */
7274 #endif /* !defined(HAVE_LONGLONG) */
7276 /****************************************************************************
7277 Get a lock offset, dealing with large offset requests.
7278 ****************************************************************************/
7280 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7281 bool large_file_format, bool *err)
7283 uint64_t offset = 0;
7287 if(!large_file_format) {
7288 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7291 #if defined(HAVE_LONGLONG)
7292 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7293 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7294 #else /* HAVE_LONGLONG */
7297 * NT4.x seems to be broken in that it sends large file (64 bit)
7298 * lockingX calls even if the CAP_LARGE_FILES was *not*
7299 * negotiated. For boxes without large unsigned ints mangle the
7300 * lock offset by mapping the top 32 bits onto the lower 32.
7303 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7304 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7305 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7308 if((new_low = map_lock_offset(high, low)) == 0) {
7310 return (uint64_t)-1;
7313 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7314 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7315 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7316 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7319 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7320 #endif /* HAVE_LONGLONG */
7326 NTSTATUS smbd_do_locking(struct smb_request *req,
7330 uint16_t num_ulocks,
7331 struct smbd_lock_element *ulocks,
7333 struct smbd_lock_element *locks,
7336 connection_struct *conn = req->conn;
7338 NTSTATUS status = NT_STATUS_OK;
7342 /* Data now points at the beginning of the list
7343 of smb_unlkrng structs */
7344 for(i = 0; i < (int)num_ulocks; i++) {
7345 struct smbd_lock_element *e = &ulocks[i];
7347 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7348 "pid %u, file %s\n",
7351 (unsigned int)e->smblctx,
7354 if (e->brltype != UNLOCK_LOCK) {
7355 /* this can only happen with SMB2 */
7356 return NT_STATUS_INVALID_PARAMETER;
7359 status = do_unlock(req->sconn->msg_ctx,
7366 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7367 nt_errstr(status)));
7369 if (!NT_STATUS_IS_OK(status)) {
7374 /* Setup the timeout in seconds. */
7376 if (!lp_blocking_locks(SNUM(conn))) {
7380 /* Data now points at the beginning of the list
7381 of smb_lkrng structs */
7383 for(i = 0; i < (int)num_locks; i++) {
7384 struct smbd_lock_element *e = &locks[i];
7386 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7387 "%llu, file %s timeout = %d\n",
7390 (unsigned long long)e->smblctx,
7394 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7395 struct blocking_lock_record *blr = NULL;
7397 if (num_locks > 1) {
7399 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7400 * if the lock vector contains one entry. When given mutliple cancel
7401 * requests in a single PDU we expect the server to return an
7402 * error. Windows servers seem to accept the request but only
7403 * cancel the first lock.
7404 * JRA - Do what Windows does (tm) :-).
7408 /* MS-CIFS (2.2.4.32.1) behavior. */
7409 return NT_STATUS_DOS(ERRDOS,
7410 ERRcancelviolation);
7412 /* Windows behavior. */
7414 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7415 "cancel request\n"));
7421 if (lp_blocking_locks(SNUM(conn))) {
7423 /* Schedule a message to ourselves to
7424 remove the blocking lock record and
7425 return the right error. */
7427 blr = blocking_lock_cancel_smb1(fsp,
7433 NT_STATUS_FILE_LOCK_CONFLICT);
7435 return NT_STATUS_DOS(
7437 ERRcancelviolation);
7440 /* Remove a matching pending lock. */
7441 status = do_lock_cancel(fsp,
7448 bool blocking_lock = timeout ? true : false;
7449 bool defer_lock = false;
7450 struct byte_range_lock *br_lck;
7451 uint64_t block_smblctx;
7453 br_lck = do_lock(req->sconn->msg_ctx,
7465 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7466 /* Windows internal resolution for blocking locks seems
7467 to be about 200ms... Don't wait for less than that. JRA. */
7468 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7469 timeout = lp_lock_spin_time();
7474 /* If a lock sent with timeout of zero would fail, and
7475 * this lock has been requested multiple times,
7476 * according to brl_lock_failed() we convert this
7477 * request to a blocking lock with a timeout of between
7478 * 150 - 300 milliseconds.
7480 * If lp_lock_spin_time() has been set to 0, we skip
7481 * this blocking retry and fail immediately.
7483 * Replacement for do_lock_spin(). JRA. */
7485 if (!req->sconn->using_smb2 &&
7486 br_lck && lp_blocking_locks(SNUM(conn)) &&
7487 lp_lock_spin_time() && !blocking_lock &&
7488 NT_STATUS_EQUAL((status),
7489 NT_STATUS_FILE_LOCK_CONFLICT))
7492 timeout = lp_lock_spin_time();
7495 if (br_lck && defer_lock) {
7497 * A blocking lock was requested. Package up
7498 * this smb into a queued request and push it
7499 * onto the blocking lock queue.
7501 if(push_blocking_lock_request(br_lck,
7512 TALLOC_FREE(br_lck);
7514 return NT_STATUS_OK;
7518 TALLOC_FREE(br_lck);
7521 if (!NT_STATUS_IS_OK(status)) {
7526 /* If any of the above locks failed, then we must unlock
7527 all of the previous locks (X/Open spec). */
7529 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7531 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7532 i = -1; /* we want to skip the for loop */
7536 * Ensure we don't do a remove on the lock that just failed,
7537 * as under POSIX rules, if we have a lock already there, we
7538 * will delete it (and we shouldn't) .....
7540 for(i--; i >= 0; i--) {
7541 struct smbd_lock_element *e = &locks[i];
7543 do_unlock(req->sconn->msg_ctx,
7553 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7554 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7556 return NT_STATUS_OK;
7559 /****************************************************************************
7560 Reply to a lockingX request.
7561 ****************************************************************************/
7563 void reply_lockingX(struct smb_request *req)
7565 connection_struct *conn = req->conn;
7567 unsigned char locktype;
7568 unsigned char oplocklevel;
7573 const uint8_t *data;
7574 bool large_file_format;
7576 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7577 struct smbd_lock_element *ulocks;
7578 struct smbd_lock_element *locks;
7581 START_PROFILE(SMBlockingX);
7584 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7585 END_PROFILE(SMBlockingX);
7589 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7590 locktype = CVAL(req->vwv+3, 0);
7591 oplocklevel = CVAL(req->vwv+3, 1);
7592 num_ulocks = SVAL(req->vwv+6, 0);
7593 num_locks = SVAL(req->vwv+7, 0);
7594 lock_timeout = IVAL(req->vwv+4, 0);
7595 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7597 if (!check_fsp(conn, req, fsp)) {
7598 END_PROFILE(SMBlockingX);
7604 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7605 /* we don't support these - and CANCEL_LOCK makes w2k
7606 and XP reboot so I don't really want to be
7607 compatible! (tridge) */
7608 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7609 END_PROFILE(SMBlockingX);
7613 /* Check if this is an oplock break on a file
7614 we have granted an oplock on.
7616 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7617 /* Client can insist on breaking to none. */
7618 bool break_to_none = (oplocklevel == 0);
7621 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7622 "for fnum = %d\n", (unsigned int)oplocklevel,
7626 * Make sure we have granted an exclusive or batch oplock on
7630 if (fsp->oplock_type == 0) {
7632 /* The Samba4 nbench simulator doesn't understand
7633 the difference between break to level2 and break
7634 to none from level2 - it sends oplock break
7635 replies in both cases. Don't keep logging an error
7636 message here - just ignore it. JRA. */
7638 DEBUG(5,("reply_lockingX: Error : oplock break from "
7639 "client for fnum = %d (oplock=%d) and no "
7640 "oplock granted on this file (%s).\n",
7641 fsp->fnum, fsp->oplock_type,
7644 /* if this is a pure oplock break request then don't
7646 if (num_locks == 0 && num_ulocks == 0) {
7647 END_PROFILE(SMBlockingX);
7650 END_PROFILE(SMBlockingX);
7651 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7656 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7658 result = remove_oplock(fsp);
7660 result = downgrade_oplock(fsp);
7664 DEBUG(0, ("reply_lockingX: error in removing "
7665 "oplock on file %s\n", fsp_str_dbg(fsp)));
7666 /* Hmmm. Is this panic justified? */
7667 smb_panic("internal tdb error");
7670 reply_to_oplock_break_requests(fsp);
7672 /* if this is a pure oplock break request then don't send a
7674 if (num_locks == 0 && num_ulocks == 0) {
7675 /* Sanity check - ensure a pure oplock break is not a
7677 if(CVAL(req->vwv+0, 0) != 0xff)
7678 DEBUG(0,("reply_lockingX: Error : pure oplock "
7679 "break is a chained %d request !\n",
7680 (unsigned int)CVAL(req->vwv+0, 0)));
7681 END_PROFILE(SMBlockingX);
7687 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7688 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7689 END_PROFILE(SMBlockingX);
7693 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7694 if (ulocks == NULL) {
7695 reply_nterror(req, NT_STATUS_NO_MEMORY);
7696 END_PROFILE(SMBlockingX);
7700 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7701 if (locks == NULL) {
7702 reply_nterror(req, NT_STATUS_NO_MEMORY);
7703 END_PROFILE(SMBlockingX);
7707 /* Data now points at the beginning of the list
7708 of smb_unlkrng structs */
7709 for(i = 0; i < (int)num_ulocks; i++) {
7710 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7711 ulocks[i].count = get_lock_count(data, i, large_file_format);
7712 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7713 ulocks[i].brltype = UNLOCK_LOCK;
7716 * There is no error code marked "stupid client bug".... :-).
7719 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7720 END_PROFILE(SMBlockingX);
7725 /* Now do any requested locks */
7726 data += ((large_file_format ? 20 : 10)*num_ulocks);
7728 /* Data now points at the beginning of the list
7729 of smb_lkrng structs */
7731 for(i = 0; i < (int)num_locks; i++) {
7732 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7733 locks[i].count = get_lock_count(data, i, large_file_format);
7734 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7736 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7737 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7738 locks[i].brltype = PENDING_READ_LOCK;
7740 locks[i].brltype = READ_LOCK;
7743 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7744 locks[i].brltype = PENDING_WRITE_LOCK;
7746 locks[i].brltype = WRITE_LOCK;
7751 * There is no error code marked "stupid client bug".... :-).
7754 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7755 END_PROFILE(SMBlockingX);
7760 status = smbd_do_locking(req, fsp,
7761 locktype, lock_timeout,
7765 if (!NT_STATUS_IS_OK(status)) {
7766 END_PROFILE(SMBlockingX);
7767 reply_nterror(req, status);
7771 END_PROFILE(SMBlockingX);
7775 reply_outbuf(req, 2, 0);
7777 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7778 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7780 END_PROFILE(SMBlockingX);
7785 #define DBGC_CLASS DBGC_ALL
7787 /****************************************************************************
7788 Reply to a SMBreadbmpx (read block multiplex) request.
7789 Always reply with an error, if someone has a platform really needs this,
7790 please contact vl@samba.org
7791 ****************************************************************************/
7793 void reply_readbmpx(struct smb_request *req)
7795 START_PROFILE(SMBreadBmpx);
7796 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7797 END_PROFILE(SMBreadBmpx);
7801 /****************************************************************************
7802 Reply to a SMBreadbs (read block multiplex secondary) request.
7803 Always reply with an error, if someone has a platform really needs this,
7804 please contact vl@samba.org
7805 ****************************************************************************/
7807 void reply_readbs(struct smb_request *req)
7809 START_PROFILE(SMBreadBs);
7810 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7811 END_PROFILE(SMBreadBs);
7815 /****************************************************************************
7816 Reply to a SMBsetattrE.
7817 ****************************************************************************/
7819 void reply_setattrE(struct smb_request *req)
7821 connection_struct *conn = req->conn;
7822 struct smb_file_time ft;
7826 START_PROFILE(SMBsetattrE);
7830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7834 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7836 if(!fsp || (fsp->conn != conn)) {
7837 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7842 * Convert the DOS times into unix times.
7845 ft.atime = convert_time_t_to_timespec(
7846 srv_make_unix_date2(req->vwv+3));
7847 ft.mtime = convert_time_t_to_timespec(
7848 srv_make_unix_date2(req->vwv+5));
7849 ft.create_time = convert_time_t_to_timespec(
7850 srv_make_unix_date2(req->vwv+1));
7852 reply_outbuf(req, 0, 0);
7855 * Patch from Ray Frush <frush@engr.colostate.edu>
7856 * Sometimes times are sent as zero - ignore them.
7859 /* Ensure we have a valid stat struct for the source. */
7860 status = vfs_stat_fsp(fsp);
7861 if (!NT_STATUS_IS_OK(status)) {
7862 reply_nterror(req, status);
7866 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7867 if (!NT_STATUS_IS_OK(status)) {
7868 reply_nterror(req, status);
7872 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7875 (unsigned int)ft.atime.tv_sec,
7876 (unsigned int)ft.mtime.tv_sec,
7877 (unsigned int)ft.create_time.tv_sec
7880 END_PROFILE(SMBsetattrE);
7885 /* Back from the dead for OS/2..... JRA. */
7887 /****************************************************************************
7888 Reply to a SMBwritebmpx (write block multiplex primary) request.
7889 Always reply with an error, if someone has a platform really needs this,
7890 please contact vl@samba.org
7891 ****************************************************************************/
7893 void reply_writebmpx(struct smb_request *req)
7895 START_PROFILE(SMBwriteBmpx);
7896 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7897 END_PROFILE(SMBwriteBmpx);
7901 /****************************************************************************
7902 Reply to a SMBwritebs (write block multiplex secondary) request.
7903 Always reply with an error, if someone has a platform really needs this,
7904 please contact vl@samba.org
7905 ****************************************************************************/
7907 void reply_writebs(struct smb_request *req)
7909 START_PROFILE(SMBwriteBs);
7910 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7911 END_PROFILE(SMBwriteBs);
7915 /****************************************************************************
7916 Reply to a SMBgetattrE.
7917 ****************************************************************************/
7919 void reply_getattrE(struct smb_request *req)
7921 connection_struct *conn = req->conn;
7924 struct timespec create_ts;
7926 START_PROFILE(SMBgetattrE);
7929 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7930 END_PROFILE(SMBgetattrE);
7934 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7936 if(!fsp || (fsp->conn != conn)) {
7937 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7938 END_PROFILE(SMBgetattrE);
7942 /* Do an fstat on this file */
7944 reply_nterror(req, map_nt_error_from_unix(errno));
7945 END_PROFILE(SMBgetattrE);
7949 mode = dos_mode(conn, fsp->fsp_name);
7952 * Convert the times into dos times. Set create
7953 * date to be last modify date as UNIX doesn't save
7957 reply_outbuf(req, 11, 0);
7959 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7960 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7961 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7962 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7963 /* Should we check pending modtime here ? JRA */
7964 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7965 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7968 SIVAL(req->outbuf, smb_vwv6, 0);
7969 SIVAL(req->outbuf, smb_vwv8, 0);
7971 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7972 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7973 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7975 SSVAL(req->outbuf,smb_vwv10, mode);
7977 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7979 END_PROFILE(SMBgetattrE);