s3:selftest: introduce a variable for binpath('net') in tests.py
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blobd01ff905a374a6ac6b52e456bf1caef532a6857c
1 /*
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
27 #include "includes.h"
28 #include "system/filesys.h"
29 #include "printing.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
41 #include "auth.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
45 /****************************************************************************
46 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
47 path or anything including wildcards.
48 We're assuming here that '/' is not the second byte in any multibyte char
49 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
50 set.
51 ****************************************************************************/
53 /* Custom version for processing POSIX paths. */
54 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
56 static NTSTATUS check_path_syntax_internal(char *path,
57 bool posix_path,
58 bool *p_last_component_contains_wcard)
60 char *d = path;
61 const char *s = path;
62 NTSTATUS ret = NT_STATUS_OK;
63 bool start_of_name_component = True;
64 bool stream_started = false;
66 *p_last_component_contains_wcard = False;
68 while (*s) {
69 if (stream_started) {
70 switch (*s) {
71 case '/':
72 case '\\':
73 return NT_STATUS_OBJECT_NAME_INVALID;
74 case ':':
75 if (s[1] == '\0') {
76 return NT_STATUS_OBJECT_NAME_INVALID;
78 if (strchr_m(&s[1], ':')) {
79 return NT_STATUS_OBJECT_NAME_INVALID;
81 break;
85 if ((*s == ':') && !posix_path && !stream_started) {
86 if (*p_last_component_contains_wcard) {
87 return NT_STATUS_OBJECT_NAME_INVALID;
89 /* Stream names allow more characters than file names.
90 We're overloading posix_path here to allow a wider
91 range of characters. If stream_started is true this
92 is still a Windows path even if posix_path is true.
93 JRA.
95 stream_started = true;
96 start_of_name_component = false;
97 posix_path = true;
99 if (s[1] == '\0') {
100 return NT_STATUS_OBJECT_NAME_INVALID;
104 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
106 * Safe to assume is not the second part of a mb char
107 * as this is handled below.
109 /* Eat multiple '/' or '\\' */
110 while (IS_PATH_SEP(*s,posix_path)) {
111 s++;
113 if ((d != path) && (*s != '\0')) {
114 /* We only care about non-leading or trailing '/' or '\\' */
115 *d++ = '/';
118 start_of_name_component = True;
119 /* New component. */
120 *p_last_component_contains_wcard = False;
121 continue;
124 if (start_of_name_component) {
125 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
126 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
129 * No mb char starts with '.' so we're safe checking the directory separator here.
132 /* If we just added a '/' - delete it */
133 if ((d > path) && (*(d-1) == '/')) {
134 *(d-1) = '\0';
135 d--;
138 /* Are we at the start ? Can't go back further if so. */
139 if (d <= path) {
140 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
141 break;
143 /* Go back one level... */
144 /* We know this is safe as '/' cannot be part of a mb sequence. */
145 /* NOTE - if this assumption is invalid we are not in good shape... */
146 /* Decrement d first as d points to the *next* char to write into. */
147 for (d--; d > path; d--) {
148 if (*d == '/')
149 break;
151 s += 2; /* Else go past the .. */
152 /* We're still at the start of a name component, just the previous one. */
153 continue;
155 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
156 if (posix_path) {
157 /* Eat the '.' */
158 s++;
159 continue;
165 if (!(*s & 0x80)) {
166 if (!posix_path) {
167 if (*s <= 0x1f || *s == '|') {
168 return NT_STATUS_OBJECT_NAME_INVALID;
170 switch (*s) {
171 case '*':
172 case '?':
173 case '<':
174 case '>':
175 case '"':
176 *p_last_component_contains_wcard = True;
177 break;
178 default:
179 break;
182 *d++ = *s++;
183 } else {
184 size_t siz;
185 /* Get the size of the next MB character. */
186 next_codepoint(s,&siz);
187 switch(siz) {
188 case 5:
189 *d++ = *s++;
190 /*fall through*/
191 case 4:
192 *d++ = *s++;
193 /*fall through*/
194 case 3:
195 *d++ = *s++;
196 /*fall through*/
197 case 2:
198 *d++ = *s++;
199 /*fall through*/
200 case 1:
201 *d++ = *s++;
202 break;
203 default:
204 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
205 *d = '\0';
206 return NT_STATUS_INVALID_PARAMETER;
209 start_of_name_component = False;
212 *d = '\0';
214 return ret;
217 /****************************************************************************
218 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
219 No wildcards allowed.
220 ****************************************************************************/
222 NTSTATUS check_path_syntax(char *path)
224 bool ignore;
225 return check_path_syntax_internal(path, False, &ignore);
228 /****************************************************************************
229 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
230 Wildcards allowed - p_contains_wcard returns true if the last component contained
231 a wildcard.
232 ****************************************************************************/
234 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
236 return check_path_syntax_internal(path, False, p_contains_wcard);
239 /****************************************************************************
240 Check the path for a POSIX client.
241 We're assuming here that '/' is not the second byte in any multibyte char
242 set (a safe assumption).
243 ****************************************************************************/
245 NTSTATUS check_path_syntax_posix(char *path)
247 bool ignore;
248 return check_path_syntax_internal(path, True, &ignore);
251 /****************************************************************************
252 Pull a string and check the path allowing a wilcard - provide for error return.
253 ****************************************************************************/
255 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
256 const char *base_ptr,
257 uint16 smb_flags2,
258 char **pp_dest,
259 const char *src,
260 size_t src_len,
261 int flags,
262 NTSTATUS *err,
263 bool *contains_wcard)
265 size_t ret;
267 *pp_dest = NULL;
269 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
270 src_len, flags);
272 if (!*pp_dest) {
273 *err = NT_STATUS_INVALID_PARAMETER;
274 return ret;
277 *contains_wcard = False;
279 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
281 * For a DFS path the function parse_dfs_path()
282 * will do the path processing, just make a copy.
284 *err = NT_STATUS_OK;
285 return ret;
288 if (lp_posix_pathnames()) {
289 *err = check_path_syntax_posix(*pp_dest);
290 } else {
291 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
294 return ret;
297 /****************************************************************************
298 Pull a string and check the path - provide for error return.
299 ****************************************************************************/
301 size_t srvstr_get_path(TALLOC_CTX *ctx,
302 const char *base_ptr,
303 uint16 smb_flags2,
304 char **pp_dest,
305 const char *src,
306 size_t src_len,
307 int flags,
308 NTSTATUS *err)
310 bool ignore;
311 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
312 src_len, flags, err, &ignore);
315 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
316 char **pp_dest, const char *src, int flags,
317 NTSTATUS *err, bool *contains_wcard)
319 return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf, req->flags2,
320 pp_dest, src, smbreq_bufrem(req, src),
321 flags, err, contains_wcard);
324 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
325 char **pp_dest, const char *src, int flags,
326 NTSTATUS *err)
328 bool ignore;
329 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
330 flags, err, &ignore);
333 /****************************************************************************
334 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
335 ****************************************************************************/
337 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
338 files_struct *fsp)
340 if ((fsp == NULL) || (conn == NULL)) {
341 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
342 return False;
344 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
345 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
346 return False;
348 return True;
351 /****************************************************************************
352 Check if we have a correct fsp pointing to a file.
353 ****************************************************************************/
355 bool check_fsp(connection_struct *conn, struct smb_request *req,
356 files_struct *fsp)
358 if (!check_fsp_open(conn, req, fsp)) {
359 return False;
361 if (fsp->is_directory) {
362 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
363 return False;
365 if (fsp->fh->fd == -1) {
366 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
367 return False;
369 fsp->num_smb_operations++;
370 return True;
373 /****************************************************************************
374 Check if we have a correct fsp pointing to a quota fake file. Replacement for
375 the CHECK_NTQUOTA_HANDLE_OK macro.
376 ****************************************************************************/
378 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
379 files_struct *fsp)
381 if (!check_fsp_open(conn, req, fsp)) {
382 return false;
385 if (fsp->is_directory) {
386 return false;
389 if (fsp->fake_file_handle == NULL) {
390 return false;
393 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
394 return false;
397 if (fsp->fake_file_handle->private_data == NULL) {
398 return false;
401 return true;
404 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
405 const char *name, int name_type)
407 char *trim_name;
408 char *trim_name_type;
409 const char *retarget_parm;
410 char *retarget;
411 char *p;
412 int retarget_type = 0x20;
413 int retarget_port = NBT_SMB_PORT;
414 struct sockaddr_storage retarget_addr;
415 struct sockaddr_in *in_addr;
416 bool ret = false;
417 uint8_t outbuf[10];
419 if (get_socket_port(sconn->sock) != NBT_SMB_PORT) {
420 return false;
423 trim_name = talloc_strdup(talloc_tos(), name);
424 if (trim_name == NULL) {
425 goto fail;
427 trim_char(trim_name, ' ', ' ');
429 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
430 name_type);
431 if (trim_name_type == NULL) {
432 goto fail;
435 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
436 trim_name_type, NULL);
437 if (retarget_parm == NULL) {
438 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
439 trim_name, NULL);
441 if (retarget_parm == NULL) {
442 goto fail;
445 retarget = talloc_strdup(trim_name, retarget_parm);
446 if (retarget == NULL) {
447 goto fail;
450 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
452 p = strchr(retarget, ':');
453 if (p != NULL) {
454 *p++ = '\0';
455 retarget_port = atoi(p);
458 p = strchr_m(retarget, '#');
459 if (p != NULL) {
460 *p++ = '\0';
461 if (sscanf(p, "%x", &retarget_type) != 1) {
462 goto fail;
466 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
467 if (!ret) {
468 DEBUG(10, ("could not resolve %s\n", retarget));
469 goto fail;
472 if (retarget_addr.ss_family != AF_INET) {
473 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
474 goto fail;
477 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
479 _smb_setlen(outbuf, 6);
480 SCVAL(outbuf, 0, 0x84);
481 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
482 *(uint16_t *)(outbuf+8) = htons(retarget_port);
484 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
485 NULL)) {
486 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
487 "failed.");
490 ret = true;
491 fail:
492 TALLOC_FREE(trim_name);
493 return ret;
496 static void reply_called_name_not_present(char *outbuf)
498 smb_setlen(outbuf, 1);
499 SCVAL(outbuf, 0, 0x83);
500 SCVAL(outbuf, 4, 0x82);
503 /****************************************************************************
504 Reply to a (netbios-level) special message.
505 ****************************************************************************/
507 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
509 int msg_type = CVAL(inbuf,0);
510 int msg_flags = CVAL(inbuf,1);
512 * We only really use 4 bytes of the outbuf, but for the smb_setlen
513 * calculation & friends (srv_send_smb uses that) we need the full smb
514 * header.
516 char outbuf[smb_size];
518 memset(outbuf, '\0', sizeof(outbuf));
520 smb_setlen(outbuf,0);
522 switch (msg_type) {
523 case NBSSrequest: /* session request */
525 /* inbuf_size is guarenteed to be at least 4. */
526 fstring name1,name2;
527 int name_type1, name_type2;
528 int name_len1, name_len2;
530 *name1 = *name2 = 0;
532 if (sconn->nbt.got_session) {
533 exit_server_cleanly("multiple session request not permitted");
536 SCVAL(outbuf,0,NBSSpositive);
537 SCVAL(outbuf,3,0);
539 /* inbuf_size is guaranteed to be at least 4. */
540 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
541 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
542 DEBUG(0,("Invalid name length in session request\n"));
543 reply_called_name_not_present(outbuf);
544 break;
546 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
547 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
548 DEBUG(0,("Invalid name length in session request\n"));
549 reply_called_name_not_present(outbuf);
550 break;
553 name_type1 = name_extract((unsigned char *)inbuf,
554 inbuf_size,(unsigned int)4,name1);
555 name_type2 = name_extract((unsigned char *)inbuf,
556 inbuf_size,(unsigned int)(4 + name_len1),name2);
558 if (name_type1 == -1 || name_type2 == -1) {
559 DEBUG(0,("Invalid name type in session request\n"));
560 reply_called_name_not_present(outbuf);
561 break;
564 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
565 name1, name_type1, name2, name_type2));
567 if (netbios_session_retarget(sconn, name1, name_type1)) {
568 exit_server_cleanly("retargeted client");
572 * Windows NT/2k uses "*SMBSERVER" and XP uses
573 * "*SMBSERV" arrggg!!!
575 if (strequal(name1, "*SMBSERVER ")
576 || strequal(name1, "*SMBSERV ")) {
577 char *raddr;
579 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
580 talloc_tos());
581 if (raddr == NULL) {
582 exit_server_cleanly("could not allocate raddr");
585 fstrcpy(name1, raddr);
588 set_local_machine_name(name1, True);
589 set_remote_machine_name(name2, True);
591 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
592 get_local_machine_name(), get_remote_machine_name(),
593 name_type2));
595 if (name_type2 == 'R') {
596 /* We are being asked for a pathworks session ---
597 no thanks! */
598 reply_called_name_not_present(outbuf);
599 break;
602 reload_services(sconn, conn_snum_used, true);
603 reopen_logs();
605 sconn->nbt.got_session = true;
606 break;
609 case 0x89: /* session keepalive request
610 (some old clients produce this?) */
611 SCVAL(outbuf,0,NBSSkeepalive);
612 SCVAL(outbuf,3,0);
613 break;
615 case NBSSpositive: /* positive session response */
616 case NBSSnegative: /* negative session response */
617 case NBSSretarget: /* retarget session response */
618 DEBUG(0,("Unexpected session response\n"));
619 break;
621 case NBSSkeepalive: /* session keepalive */
622 default:
623 return;
626 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
627 msg_type, msg_flags));
629 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
631 if (CVAL(outbuf, 0) != 0x82) {
632 exit_server_cleanly("invalid netbios session");
634 return;
637 /****************************************************************************
638 Reply to a tcon.
639 conn POINTER CAN BE NULL HERE !
640 ****************************************************************************/
642 void reply_tcon(struct smb_request *req)
644 connection_struct *conn = req->conn;
645 const char *service;
646 char *service_buf = NULL;
647 char *password = NULL;
648 char *dev = NULL;
649 int pwlen=0;
650 NTSTATUS nt_status;
651 const char *p;
652 TALLOC_CTX *ctx = talloc_tos();
653 struct smbd_server_connection *sconn = req->sconn;
655 START_PROFILE(SMBtcon);
657 if (req->buflen < 4) {
658 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
659 END_PROFILE(SMBtcon);
660 return;
663 p = (const char *)req->buf + 1;
664 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
665 p += 1;
666 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
667 p += pwlen+1;
668 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
669 p += 1;
671 if (service_buf == NULL || password == NULL || dev == NULL) {
672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
673 END_PROFILE(SMBtcon);
674 return;
676 p = strrchr_m(service_buf,'\\');
677 if (p) {
678 service = p+1;
679 } else {
680 service = service_buf;
683 conn = make_connection(sconn,service,dev,
684 req->vuid,&nt_status);
685 req->conn = conn;
687 if (!conn) {
688 reply_nterror(req, nt_status);
689 END_PROFILE(SMBtcon);
690 return;
693 reply_outbuf(req, 2, 0);
694 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
695 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
696 SSVAL(req->outbuf,smb_tid,conn->cnum);
698 DEBUG(3,("tcon service=%s cnum=%d\n",
699 service, conn->cnum));
701 END_PROFILE(SMBtcon);
702 return;
705 /****************************************************************************
706 Reply to a tcon and X.
707 conn POINTER CAN BE NULL HERE !
708 ****************************************************************************/
710 void reply_tcon_and_X(struct smb_request *req)
712 connection_struct *conn = req->conn;
713 const char *service = NULL;
714 TALLOC_CTX *ctx = talloc_tos();
715 /* what the cleint thinks the device is */
716 char *client_devicetype = NULL;
717 /* what the server tells the client the share represents */
718 const char *server_devicetype;
719 NTSTATUS nt_status;
720 int passlen;
721 char *path = NULL;
722 const char *p, *q;
723 uint16 tcon_flags;
724 struct smbd_server_connection *sconn = req->sconn;
726 START_PROFILE(SMBtconX);
728 if (req->wct < 4) {
729 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
730 END_PROFILE(SMBtconX);
731 return;
734 passlen = SVAL(req->vwv+3, 0);
735 tcon_flags = SVAL(req->vwv+2, 0);
737 /* we might have to close an old one */
738 if ((tcon_flags & 0x1) && conn) {
739 close_cnum(conn,req->vuid);
740 req->conn = NULL;
741 conn = NULL;
744 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
745 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
746 END_PROFILE(SMBtconX);
747 return;
750 if (sconn->smb1.negprot.encrypted_passwords) {
751 p = (const char *)req->buf + passlen;
752 } else {
753 p = (const char *)req->buf + passlen + 1;
756 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
758 if (path == NULL) {
759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
760 END_PROFILE(SMBtconX);
761 return;
765 * the service name can be either: \\server\share
766 * or share directly like on the DELL PowerVault 705
768 if (*path=='\\') {
769 q = strchr_m(path+2,'\\');
770 if (!q) {
771 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
772 END_PROFILE(SMBtconX);
773 return;
775 service = q+1;
776 } else {
777 service = path;
780 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
781 &client_devicetype, p,
782 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
784 if (client_devicetype == NULL) {
785 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
786 END_PROFILE(SMBtconX);
787 return;
790 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
792 conn = make_connection(sconn, service, client_devicetype,
793 req->vuid, &nt_status);
794 req->conn =conn;
796 if (!conn) {
797 reply_nterror(req, nt_status);
798 END_PROFILE(SMBtconX);
799 return;
802 if ( IS_IPC(conn) )
803 server_devicetype = "IPC";
804 else if ( IS_PRINT(conn) )
805 server_devicetype = "LPT1:";
806 else
807 server_devicetype = "A:";
809 if (get_Protocol() < PROTOCOL_NT1) {
810 reply_outbuf(req, 2, 0);
811 if (message_push_string(&req->outbuf, server_devicetype,
812 STR_TERMINATE|STR_ASCII) == -1) {
813 reply_nterror(req, NT_STATUS_NO_MEMORY);
814 END_PROFILE(SMBtconX);
815 return;
817 } else {
818 /* NT sets the fstype of IPC$ to the null string */
819 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
821 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
822 /* Return permissions. */
823 uint32 perm1 = 0;
824 uint32 perm2 = 0;
826 reply_outbuf(req, 7, 0);
828 if (IS_IPC(conn)) {
829 perm1 = FILE_ALL_ACCESS;
830 perm2 = FILE_ALL_ACCESS;
831 } else {
832 perm1 = conn->share_access;
835 SIVAL(req->outbuf, smb_vwv3, perm1);
836 SIVAL(req->outbuf, smb_vwv5, perm2);
837 } else {
838 reply_outbuf(req, 3, 0);
841 if ((message_push_string(&req->outbuf, server_devicetype,
842 STR_TERMINATE|STR_ASCII) == -1)
843 || (message_push_string(&req->outbuf, fstype,
844 STR_TERMINATE) == -1)) {
845 reply_nterror(req, NT_STATUS_NO_MEMORY);
846 END_PROFILE(SMBtconX);
847 return;
850 /* what does setting this bit do? It is set by NT4 and
851 may affect the ability to autorun mounted cdroms */
852 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
853 (lp_csc_policy(SNUM(conn)) << 2));
855 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
856 DEBUG(2,("Serving %s as a Dfs root\n",
857 lp_servicename(SNUM(conn)) ));
858 SSVAL(req->outbuf, smb_vwv2,
859 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
863 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
864 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
866 DEBUG(3,("tconX service=%s \n",
867 service));
869 /* set the incoming and outgoing tid to the just created one */
870 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
871 SSVAL(req->outbuf,smb_tid,conn->cnum);
873 END_PROFILE(SMBtconX);
875 req->tid = conn->cnum;
878 /****************************************************************************
879 Reply to an unknown type.
880 ****************************************************************************/
882 void reply_unknown_new(struct smb_request *req, uint8 type)
884 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
885 smb_fn_name(type), type, type));
886 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
887 return;
890 /****************************************************************************
891 Reply to an ioctl.
892 conn POINTER CAN BE NULL HERE !
893 ****************************************************************************/
895 void reply_ioctl(struct smb_request *req)
897 connection_struct *conn = req->conn;
898 uint16 device;
899 uint16 function;
900 uint32 ioctl_code;
901 int replysize;
902 char *p;
904 START_PROFILE(SMBioctl);
906 if (req->wct < 3) {
907 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
908 END_PROFILE(SMBioctl);
909 return;
912 device = SVAL(req->vwv+1, 0);
913 function = SVAL(req->vwv+2, 0);
914 ioctl_code = (device << 16) + function;
916 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
918 switch (ioctl_code) {
919 case IOCTL_QUERY_JOB_INFO:
920 replysize = 32;
921 break;
922 default:
923 reply_force_doserror(req, ERRSRV, ERRnosupport);
924 END_PROFILE(SMBioctl);
925 return;
928 reply_outbuf(req, 8, replysize+1);
929 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
930 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
931 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
932 p = smb_buf(req->outbuf);
933 memset(p, '\0', replysize+1); /* valgrind-safe. */
934 p += 1; /* Allow for alignment */
936 switch (ioctl_code) {
937 case IOCTL_QUERY_JOB_INFO:
939 files_struct *fsp = file_fsp(
940 req, SVAL(req->vwv+0, 0));
941 if (!fsp) {
942 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
943 END_PROFILE(SMBioctl);
944 return;
946 /* Job number */
947 if (fsp->print_file) {
948 SSVAL(p, 0, fsp->print_file->rap_jobid);
949 } else {
950 SSVAL(p, 0, 0);
952 srvstr_push((char *)req->outbuf, req->flags2, p+2,
953 lp_netbios_name(), 15,
954 STR_TERMINATE|STR_ASCII);
955 if (conn) {
956 srvstr_push((char *)req->outbuf, req->flags2,
957 p+18, lp_servicename(SNUM(conn)),
958 13, STR_TERMINATE|STR_ASCII);
959 } else {
960 memset(p+18, 0, 13);
962 break;
966 END_PROFILE(SMBioctl);
967 return;
970 /****************************************************************************
971 Strange checkpath NTSTATUS mapping.
972 ****************************************************************************/
974 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
976 /* Strange DOS error code semantics only for checkpath... */
977 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
978 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
979 /* We need to map to ERRbadpath */
980 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
983 return status;
986 /****************************************************************************
987 Reply to a checkpath.
988 ****************************************************************************/
990 void reply_checkpath(struct smb_request *req)
992 connection_struct *conn = req->conn;
993 struct smb_filename *smb_fname = NULL;
994 char *name = NULL;
995 NTSTATUS status;
996 TALLOC_CTX *ctx = talloc_tos();
998 START_PROFILE(SMBcheckpath);
1000 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1001 STR_TERMINATE, &status);
1003 if (!NT_STATUS_IS_OK(status)) {
1004 status = map_checkpath_error(req->flags2, status);
1005 reply_nterror(req, status);
1006 END_PROFILE(SMBcheckpath);
1007 return;
1010 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1012 status = filename_convert(ctx,
1013 conn,
1014 req->flags2 & FLAGS2_DFS_PATHNAMES,
1015 name,
1017 NULL,
1018 &smb_fname);
1020 if (!NT_STATUS_IS_OK(status)) {
1021 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1022 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1023 ERRSRV, ERRbadpath);
1024 END_PROFILE(SMBcheckpath);
1025 return;
1027 goto path_err;
1030 if (!VALID_STAT(smb_fname->st) &&
1031 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1032 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1033 smb_fname_str_dbg(smb_fname), strerror(errno)));
1034 status = map_nt_error_from_unix(errno);
1035 goto path_err;
1038 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1039 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1040 ERRDOS, ERRbadpath);
1041 goto out;
1044 reply_outbuf(req, 0, 0);
1046 path_err:
1047 /* We special case this - as when a Windows machine
1048 is parsing a path is steps through the components
1049 one at a time - if a component fails it expects
1050 ERRbadpath, not ERRbadfile.
1052 status = map_checkpath_error(req->flags2, status);
1053 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1055 * Windows returns different error codes if
1056 * the parent directory is valid but not the
1057 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1058 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1059 * if the path is invalid.
1061 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1062 ERRDOS, ERRbadpath);
1063 goto out;
1066 reply_nterror(req, status);
1068 out:
1069 TALLOC_FREE(smb_fname);
1070 END_PROFILE(SMBcheckpath);
1071 return;
1074 /****************************************************************************
1075 Reply to a getatr.
1076 ****************************************************************************/
1078 void reply_getatr(struct smb_request *req)
1080 connection_struct *conn = req->conn;
1081 struct smb_filename *smb_fname = NULL;
1082 char *fname = NULL;
1083 int mode=0;
1084 off_t size=0;
1085 time_t mtime=0;
1086 const char *p;
1087 NTSTATUS status;
1088 TALLOC_CTX *ctx = talloc_tos();
1089 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1091 START_PROFILE(SMBgetatr);
1093 p = (const char *)req->buf + 1;
1094 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1095 if (!NT_STATUS_IS_OK(status)) {
1096 reply_nterror(req, status);
1097 goto out;
1100 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1101 under WfWg - weird! */
1102 if (*fname == '\0') {
1103 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1104 if (!CAN_WRITE(conn)) {
1105 mode |= FILE_ATTRIBUTE_READONLY;
1107 size = 0;
1108 mtime = 0;
1109 } else {
1110 status = filename_convert(ctx,
1111 conn,
1112 req->flags2 & FLAGS2_DFS_PATHNAMES,
1113 fname,
1115 NULL,
1116 &smb_fname);
1117 if (!NT_STATUS_IS_OK(status)) {
1118 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1119 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1120 ERRSRV, ERRbadpath);
1121 goto out;
1123 reply_nterror(req, status);
1124 goto out;
1126 if (!VALID_STAT(smb_fname->st) &&
1127 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1128 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1129 smb_fname_str_dbg(smb_fname),
1130 strerror(errno)));
1131 reply_nterror(req, map_nt_error_from_unix(errno));
1132 goto out;
1135 mode = dos_mode(conn, smb_fname);
1136 size = smb_fname->st.st_ex_size;
1138 if (ask_sharemode) {
1139 struct timespec write_time_ts;
1140 struct file_id fileid;
1142 ZERO_STRUCT(write_time_ts);
1143 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1144 get_file_infos(fileid, 0, NULL, &write_time_ts);
1145 if (!null_timespec(write_time_ts)) {
1146 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1150 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1151 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1152 size = 0;
1156 reply_outbuf(req, 10, 0);
1158 SSVAL(req->outbuf,smb_vwv0,mode);
1159 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1160 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1161 } else {
1162 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1164 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1166 if (get_Protocol() >= PROTOCOL_NT1) {
1167 SSVAL(req->outbuf, smb_flg2,
1168 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1171 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1172 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1174 out:
1175 TALLOC_FREE(smb_fname);
1176 TALLOC_FREE(fname);
1177 END_PROFILE(SMBgetatr);
1178 return;
1181 /****************************************************************************
1182 Reply to a setatr.
1183 ****************************************************************************/
1185 void reply_setatr(struct smb_request *req)
1187 struct smb_file_time ft;
1188 connection_struct *conn = req->conn;
1189 struct smb_filename *smb_fname = NULL;
1190 char *fname = NULL;
1191 int mode;
1192 time_t mtime;
1193 const char *p;
1194 NTSTATUS status;
1195 TALLOC_CTX *ctx = talloc_tos();
1197 START_PROFILE(SMBsetatr);
1199 ZERO_STRUCT(ft);
1201 if (req->wct < 2) {
1202 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1203 goto out;
1206 p = (const char *)req->buf + 1;
1207 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1208 if (!NT_STATUS_IS_OK(status)) {
1209 reply_nterror(req, status);
1210 goto out;
1213 status = filename_convert(ctx,
1214 conn,
1215 req->flags2 & FLAGS2_DFS_PATHNAMES,
1216 fname,
1218 NULL,
1219 &smb_fname);
1220 if (!NT_STATUS_IS_OK(status)) {
1221 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1222 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1223 ERRSRV, ERRbadpath);
1224 goto out;
1226 reply_nterror(req, status);
1227 goto out;
1230 if (smb_fname->base_name[0] == '.' &&
1231 smb_fname->base_name[1] == '\0') {
1233 * Not sure here is the right place to catch this
1234 * condition. Might be moved to somewhere else later -- vl
1236 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1237 goto out;
1240 mode = SVAL(req->vwv+0, 0);
1241 mtime = srv_make_unix_date3(req->vwv+1);
1243 if (mode != FILE_ATTRIBUTE_NORMAL) {
1244 if (VALID_STAT_OF_DIR(smb_fname->st))
1245 mode |= FILE_ATTRIBUTE_DIRECTORY;
1246 else
1247 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1249 status = check_access(conn, NULL, smb_fname,
1250 FILE_WRITE_ATTRIBUTES);
1251 if (!NT_STATUS_IS_OK(status)) {
1252 reply_nterror(req, status);
1253 goto out;
1256 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1257 false) != 0) {
1258 reply_nterror(req, map_nt_error_from_unix(errno));
1259 goto out;
1263 ft.mtime = convert_time_t_to_timespec(mtime);
1264 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1265 if (!NT_STATUS_IS_OK(status)) {
1266 reply_nterror(req, status);
1267 goto out;
1270 reply_outbuf(req, 0, 0);
1272 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1273 mode));
1274 out:
1275 TALLOC_FREE(smb_fname);
1276 END_PROFILE(SMBsetatr);
1277 return;
1280 /****************************************************************************
1281 Reply to a dskattr.
1282 ****************************************************************************/
1284 void reply_dskattr(struct smb_request *req)
1286 connection_struct *conn = req->conn;
1287 uint64_t dfree,dsize,bsize;
1288 START_PROFILE(SMBdskattr);
1290 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1291 reply_nterror(req, map_nt_error_from_unix(errno));
1292 END_PROFILE(SMBdskattr);
1293 return;
1296 reply_outbuf(req, 5, 0);
1298 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1299 double total_space, free_space;
1300 /* we need to scale this to a number that DOS6 can handle. We
1301 use floating point so we can handle large drives on systems
1302 that don't have 64 bit integers
1304 we end up displaying a maximum of 2G to DOS systems
1306 total_space = dsize * (double)bsize;
1307 free_space = dfree * (double)bsize;
1309 dsize = (uint64_t)((total_space+63*512) / (64*512));
1310 dfree = (uint64_t)((free_space+63*512) / (64*512));
1312 if (dsize > 0xFFFF) dsize = 0xFFFF;
1313 if (dfree > 0xFFFF) dfree = 0xFFFF;
1315 SSVAL(req->outbuf,smb_vwv0,dsize);
1316 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1317 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1318 SSVAL(req->outbuf,smb_vwv3,dfree);
1319 } else {
1320 SSVAL(req->outbuf,smb_vwv0,dsize);
1321 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1322 SSVAL(req->outbuf,smb_vwv2,512);
1323 SSVAL(req->outbuf,smb_vwv3,dfree);
1326 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1328 END_PROFILE(SMBdskattr);
1329 return;
1333 * Utility function to split the filename from the directory.
1335 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1336 char **fname_dir_out,
1337 char **fname_mask_out)
1339 const char *p = NULL;
1340 char *fname_dir = NULL;
1341 char *fname_mask = NULL;
1343 p = strrchr_m(fname_in, '/');
1344 if (!p) {
1345 fname_dir = talloc_strdup(ctx, ".");
1346 fname_mask = talloc_strdup(ctx, fname_in);
1347 } else {
1348 fname_dir = talloc_strndup(ctx, fname_in,
1349 PTR_DIFF(p, fname_in));
1350 fname_mask = talloc_strdup(ctx, p+1);
1353 if (!fname_dir || !fname_mask) {
1354 TALLOC_FREE(fname_dir);
1355 TALLOC_FREE(fname_mask);
1356 return NT_STATUS_NO_MEMORY;
1359 *fname_dir_out = fname_dir;
1360 *fname_mask_out = fname_mask;
1361 return NT_STATUS_OK;
1364 /****************************************************************************
1365 Reply to a search.
1366 Can be called from SMBsearch, SMBffirst or SMBfunique.
1367 ****************************************************************************/
1369 void reply_search(struct smb_request *req)
1371 connection_struct *conn = req->conn;
1372 char *path = NULL;
1373 const char *mask = NULL;
1374 char *directory = NULL;
1375 struct smb_filename *smb_fname = NULL;
1376 char *fname = NULL;
1377 off_t size;
1378 uint32 mode;
1379 struct timespec date;
1380 uint32 dirtype;
1381 unsigned int numentries = 0;
1382 unsigned int maxentries = 0;
1383 bool finished = False;
1384 const char *p;
1385 int status_len;
1386 char status[21];
1387 int dptr_num= -1;
1388 bool check_descend = False;
1389 bool expect_close = False;
1390 NTSTATUS nt_status;
1391 bool mask_contains_wcard = False;
1392 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1393 TALLOC_CTX *ctx = talloc_tos();
1394 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1395 struct dptr_struct *dirptr = NULL;
1396 struct smbd_server_connection *sconn = req->sconn;
1398 START_PROFILE(SMBsearch);
1400 if (req->wct < 2) {
1401 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1402 goto out;
1405 if (lp_posix_pathnames()) {
1406 reply_unknown_new(req, req->cmd);
1407 goto out;
1410 /* If we were called as SMBffirst then we must expect close. */
1411 if(req->cmd == SMBffirst) {
1412 expect_close = True;
1415 reply_outbuf(req, 1, 3);
1416 maxentries = SVAL(req->vwv+0, 0);
1417 dirtype = SVAL(req->vwv+1, 0);
1418 p = (const char *)req->buf + 1;
1419 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1420 &nt_status, &mask_contains_wcard);
1421 if (!NT_STATUS_IS_OK(nt_status)) {
1422 reply_nterror(req, nt_status);
1423 goto out;
1426 p++;
1427 status_len = SVAL(p, 0);
1428 p += 2;
1430 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1432 if (status_len == 0) {
1433 nt_status = filename_convert(ctx, conn,
1434 req->flags2 & FLAGS2_DFS_PATHNAMES,
1435 path,
1436 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1437 &mask_contains_wcard,
1438 &smb_fname);
1439 if (!NT_STATUS_IS_OK(nt_status)) {
1440 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1441 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1442 ERRSRV, ERRbadpath);
1443 goto out;
1445 reply_nterror(req, nt_status);
1446 goto out;
1449 directory = smb_fname->base_name;
1451 p = strrchr_m(directory,'/');
1452 if ((p != NULL) && (*directory != '/')) {
1453 mask = p + 1;
1454 directory = talloc_strndup(ctx, directory,
1455 PTR_DIFF(p, directory));
1456 } else {
1457 mask = directory;
1458 directory = talloc_strdup(ctx,".");
1461 if (!directory) {
1462 reply_nterror(req, NT_STATUS_NO_MEMORY);
1463 goto out;
1466 memset((char *)status,'\0',21);
1467 SCVAL(status,0,(dirtype & 0x1F));
1469 nt_status = dptr_create(conn,
1470 NULL, /* req */
1471 NULL, /* fsp */
1472 directory,
1473 True,
1474 expect_close,
1475 req->smbpid,
1476 mask,
1477 mask_contains_wcard,
1478 dirtype,
1479 &dirptr);
1480 if (!NT_STATUS_IS_OK(nt_status)) {
1481 reply_nterror(req, nt_status);
1482 goto out;
1484 dptr_num = dptr_dnum(dirptr);
1485 } else {
1486 int status_dirtype;
1487 const char *dirpath;
1489 memcpy(status,p,21);
1490 status_dirtype = CVAL(status,0) & 0x1F;
1491 if (status_dirtype != (dirtype & 0x1F)) {
1492 dirtype = status_dirtype;
1495 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1496 if (!dirptr) {
1497 goto SearchEmpty;
1499 dirpath = dptr_path(sconn, dptr_num);
1500 directory = talloc_strdup(ctx, dirpath);
1501 if (!directory) {
1502 reply_nterror(req, NT_STATUS_NO_MEMORY);
1503 goto out;
1506 mask = dptr_wcard(sconn, dptr_num);
1507 if (!mask) {
1508 goto SearchEmpty;
1511 * For a 'continue' search we have no string. So
1512 * check from the initial saved string.
1514 mask_contains_wcard = ms_has_wild(mask);
1515 dirtype = dptr_attr(sconn, dptr_num);
1518 DEBUG(4,("dptr_num is %d\n",dptr_num));
1520 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1521 dptr_init_search_op(dirptr);
1523 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1524 char buf[DIR_STRUCT_SIZE];
1525 memcpy(buf,status,21);
1526 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1527 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1528 reply_nterror(req, NT_STATUS_NO_MEMORY);
1529 goto out;
1531 dptr_fill(sconn, buf+12,dptr_num);
1532 if (dptr_zero(buf+12) && (status_len==0)) {
1533 numentries = 1;
1534 } else {
1535 numentries = 0;
1537 if (message_push_blob(&req->outbuf,
1538 data_blob_const(buf, sizeof(buf)))
1539 == -1) {
1540 reply_nterror(req, NT_STATUS_NO_MEMORY);
1541 goto out;
1543 } else {
1544 unsigned int i;
1545 maxentries = MIN(
1546 maxentries,
1547 ((BUFFER_SIZE -
1548 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1549 /DIR_STRUCT_SIZE));
1551 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1552 directory,lp_dontdescend(SNUM(conn))));
1553 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1554 check_descend = True;
1557 for (i=numentries;(i<maxentries) && !finished;i++) {
1558 finished = !get_dir_entry(ctx,
1559 dirptr,
1560 mask,
1561 dirtype,
1562 &fname,
1563 &size,
1564 &mode,
1565 &date,
1566 check_descend,
1567 ask_sharemode);
1568 if (!finished) {
1569 char buf[DIR_STRUCT_SIZE];
1570 memcpy(buf,status,21);
1571 if (!make_dir_struct(ctx,
1572 buf,
1573 mask,
1574 fname,
1575 size,
1576 mode,
1577 convert_timespec_to_time_t(date),
1578 !allow_long_path_components)) {
1579 reply_nterror(req, NT_STATUS_NO_MEMORY);
1580 goto out;
1582 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1583 break;
1585 if (message_push_blob(&req->outbuf,
1586 data_blob_const(buf, sizeof(buf)))
1587 == -1) {
1588 reply_nterror(req, NT_STATUS_NO_MEMORY);
1589 goto out;
1591 numentries++;
1596 SearchEmpty:
1598 /* If we were called as SMBffirst with smb_search_id == NULL
1599 and no entries were found then return error and close dirptr
1600 (X/Open spec) */
1602 if (numentries == 0) {
1603 dptr_close(sconn, &dptr_num);
1604 } else if(expect_close && status_len == 0) {
1605 /* Close the dptr - we know it's gone */
1606 dptr_close(sconn, &dptr_num);
1609 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1610 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1611 dptr_close(sconn, &dptr_num);
1614 if ((numentries == 0) && !mask_contains_wcard) {
1615 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1616 goto out;
1619 SSVAL(req->outbuf,smb_vwv0,numentries);
1620 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1621 SCVAL(smb_buf(req->outbuf),0,5);
1622 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1624 /* The replies here are never long name. */
1625 SSVAL(req->outbuf, smb_flg2,
1626 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1627 if (!allow_long_path_components) {
1628 SSVAL(req->outbuf, smb_flg2,
1629 SVAL(req->outbuf, smb_flg2)
1630 & (~FLAGS2_LONG_PATH_COMPONENTS));
1633 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1634 SSVAL(req->outbuf, smb_flg2,
1635 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1637 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1638 smb_fn_name(req->cmd),
1639 mask,
1640 directory,
1641 dirtype,
1642 numentries,
1643 maxentries ));
1644 out:
1645 TALLOC_FREE(directory);
1646 TALLOC_FREE(smb_fname);
1647 END_PROFILE(SMBsearch);
1648 return;
1651 /****************************************************************************
1652 Reply to a fclose (stop directory search).
1653 ****************************************************************************/
1655 void reply_fclose(struct smb_request *req)
1657 int status_len;
1658 char status[21];
1659 int dptr_num= -2;
1660 const char *p;
1661 char *path = NULL;
1662 NTSTATUS err;
1663 bool path_contains_wcard = False;
1664 TALLOC_CTX *ctx = talloc_tos();
1665 struct smbd_server_connection *sconn = req->sconn;
1667 START_PROFILE(SMBfclose);
1669 if (lp_posix_pathnames()) {
1670 reply_unknown_new(req, req->cmd);
1671 END_PROFILE(SMBfclose);
1672 return;
1675 p = (const char *)req->buf + 1;
1676 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1677 &err, &path_contains_wcard);
1678 if (!NT_STATUS_IS_OK(err)) {
1679 reply_nterror(req, err);
1680 END_PROFILE(SMBfclose);
1681 return;
1683 p++;
1684 status_len = SVAL(p,0);
1685 p += 2;
1687 if (status_len == 0) {
1688 reply_force_doserror(req, ERRSRV, ERRsrverror);
1689 END_PROFILE(SMBfclose);
1690 return;
1693 memcpy(status,p,21);
1695 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1696 /* Close the dptr - we know it's gone */
1697 dptr_close(sconn, &dptr_num);
1700 reply_outbuf(req, 1, 0);
1701 SSVAL(req->outbuf,smb_vwv0,0);
1703 DEBUG(3,("search close\n"));
1705 END_PROFILE(SMBfclose);
1706 return;
1709 /****************************************************************************
1710 Reply to an open.
1711 ****************************************************************************/
1713 void reply_open(struct smb_request *req)
1715 connection_struct *conn = req->conn;
1716 struct smb_filename *smb_fname = NULL;
1717 char *fname = NULL;
1718 uint32 fattr=0;
1719 off_t size = 0;
1720 time_t mtime=0;
1721 int info;
1722 files_struct *fsp;
1723 int oplock_request;
1724 int deny_mode;
1725 uint32 dos_attr;
1726 uint32 access_mask;
1727 uint32 share_mode;
1728 uint32 create_disposition;
1729 uint32 create_options = 0;
1730 uint32_t private_flags = 0;
1731 NTSTATUS status;
1732 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1733 TALLOC_CTX *ctx = talloc_tos();
1735 START_PROFILE(SMBopen);
1737 if (req->wct < 2) {
1738 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1739 goto out;
1742 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1743 deny_mode = SVAL(req->vwv+0, 0);
1744 dos_attr = SVAL(req->vwv+1, 0);
1746 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1747 STR_TERMINATE, &status);
1748 if (!NT_STATUS_IS_OK(status)) {
1749 reply_nterror(req, status);
1750 goto out;
1753 status = filename_convert(ctx,
1754 conn,
1755 req->flags2 & FLAGS2_DFS_PATHNAMES,
1756 fname,
1758 NULL,
1759 &smb_fname);
1760 if (!NT_STATUS_IS_OK(status)) {
1761 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1762 reply_botherror(req,
1763 NT_STATUS_PATH_NOT_COVERED,
1764 ERRSRV, ERRbadpath);
1765 goto out;
1767 reply_nterror(req, status);
1768 goto out;
1771 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1772 OPENX_FILE_EXISTS_OPEN, &access_mask,
1773 &share_mode, &create_disposition,
1774 &create_options, &private_flags)) {
1775 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1776 goto out;
1779 status = SMB_VFS_CREATE_FILE(
1780 conn, /* conn */
1781 req, /* req */
1782 0, /* root_dir_fid */
1783 smb_fname, /* fname */
1784 access_mask, /* access_mask */
1785 share_mode, /* share_access */
1786 create_disposition, /* create_disposition*/
1787 create_options, /* create_options */
1788 dos_attr, /* file_attributes */
1789 oplock_request, /* oplock_request */
1790 0, /* allocation_size */
1791 private_flags,
1792 NULL, /* sd */
1793 NULL, /* ea_list */
1794 &fsp, /* result */
1795 &info); /* pinfo */
1797 if (!NT_STATUS_IS_OK(status)) {
1798 if (open_was_deferred(req->sconn, req->mid)) {
1799 /* We have re-scheduled this call. */
1800 goto out;
1802 reply_openerror(req, status);
1803 goto out;
1806 size = smb_fname->st.st_ex_size;
1807 fattr = dos_mode(conn, smb_fname);
1809 /* Deal with other possible opens having a modified
1810 write time. JRA. */
1811 if (ask_sharemode) {
1812 struct timespec write_time_ts;
1814 ZERO_STRUCT(write_time_ts);
1815 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1816 if (!null_timespec(write_time_ts)) {
1817 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1821 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1823 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1824 DEBUG(3,("attempt to open a directory %s\n",
1825 fsp_str_dbg(fsp)));
1826 close_file(req, fsp, ERROR_CLOSE);
1827 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1828 ERRDOS, ERRnoaccess);
1829 goto out;
1832 reply_outbuf(req, 7, 0);
1833 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1834 SSVAL(req->outbuf,smb_vwv1,fattr);
1835 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1836 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1837 } else {
1838 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1840 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1841 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1843 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1844 SCVAL(req->outbuf,smb_flg,
1845 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1848 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1849 SCVAL(req->outbuf,smb_flg,
1850 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1852 out:
1853 TALLOC_FREE(smb_fname);
1854 END_PROFILE(SMBopen);
1855 return;
1858 /****************************************************************************
1859 Reply to an open and X.
1860 ****************************************************************************/
1862 void reply_open_and_X(struct smb_request *req)
1864 connection_struct *conn = req->conn;
1865 struct smb_filename *smb_fname = NULL;
1866 char *fname = NULL;
1867 uint16 open_flags;
1868 int deny_mode;
1869 uint32 smb_attr;
1870 /* Breakout the oplock request bits so we can set the
1871 reply bits separately. */
1872 int ex_oplock_request;
1873 int core_oplock_request;
1874 int oplock_request;
1875 #if 0
1876 int smb_sattr = SVAL(req->vwv+4, 0);
1877 uint32 smb_time = make_unix_date3(req->vwv+6);
1878 #endif
1879 int smb_ofun;
1880 uint32 fattr=0;
1881 int mtime=0;
1882 int smb_action = 0;
1883 files_struct *fsp;
1884 NTSTATUS status;
1885 uint64_t allocation_size;
1886 ssize_t retval = -1;
1887 uint32 access_mask;
1888 uint32 share_mode;
1889 uint32 create_disposition;
1890 uint32 create_options = 0;
1891 uint32_t private_flags = 0;
1892 TALLOC_CTX *ctx = talloc_tos();
1894 START_PROFILE(SMBopenX);
1896 if (req->wct < 15) {
1897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1898 goto out;
1901 open_flags = SVAL(req->vwv+2, 0);
1902 deny_mode = SVAL(req->vwv+3, 0);
1903 smb_attr = SVAL(req->vwv+5, 0);
1904 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1905 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1906 oplock_request = ex_oplock_request | core_oplock_request;
1907 smb_ofun = SVAL(req->vwv+8, 0);
1908 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1910 /* If it's an IPC, pass off the pipe handler. */
1911 if (IS_IPC(conn)) {
1912 if (lp_nt_pipe_support()) {
1913 reply_open_pipe_and_X(conn, req);
1914 } else {
1915 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1917 goto out;
1920 /* XXXX we need to handle passed times, sattr and flags */
1921 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1922 STR_TERMINATE, &status);
1923 if (!NT_STATUS_IS_OK(status)) {
1924 reply_nterror(req, status);
1925 goto out;
1928 status = filename_convert(ctx,
1929 conn,
1930 req->flags2 & FLAGS2_DFS_PATHNAMES,
1931 fname,
1933 NULL,
1934 &smb_fname);
1935 if (!NT_STATUS_IS_OK(status)) {
1936 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1937 reply_botherror(req,
1938 NT_STATUS_PATH_NOT_COVERED,
1939 ERRSRV, ERRbadpath);
1940 goto out;
1942 reply_nterror(req, status);
1943 goto out;
1946 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1947 smb_ofun,
1948 &access_mask, &share_mode,
1949 &create_disposition,
1950 &create_options,
1951 &private_flags)) {
1952 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1953 goto out;
1956 status = SMB_VFS_CREATE_FILE(
1957 conn, /* conn */
1958 req, /* req */
1959 0, /* root_dir_fid */
1960 smb_fname, /* fname */
1961 access_mask, /* access_mask */
1962 share_mode, /* share_access */
1963 create_disposition, /* create_disposition*/
1964 create_options, /* create_options */
1965 smb_attr, /* file_attributes */
1966 oplock_request, /* oplock_request */
1967 0, /* allocation_size */
1968 private_flags,
1969 NULL, /* sd */
1970 NULL, /* ea_list */
1971 &fsp, /* result */
1972 &smb_action); /* pinfo */
1974 if (!NT_STATUS_IS_OK(status)) {
1975 if (open_was_deferred(req->sconn, req->mid)) {
1976 /* We have re-scheduled this call. */
1977 goto out;
1979 reply_openerror(req, status);
1980 goto out;
1983 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1984 if the file is truncated or created. */
1985 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1986 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1987 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1988 close_file(req, fsp, ERROR_CLOSE);
1989 reply_nterror(req, NT_STATUS_DISK_FULL);
1990 goto out;
1992 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
1993 if (retval < 0) {
1994 close_file(req, fsp, ERROR_CLOSE);
1995 reply_nterror(req, NT_STATUS_DISK_FULL);
1996 goto out;
1998 status = vfs_stat_fsp(fsp);
1999 if (!NT_STATUS_IS_OK(status)) {
2000 close_file(req, fsp, ERROR_CLOSE);
2001 reply_nterror(req, status);
2002 goto out;
2006 fattr = dos_mode(conn, fsp->fsp_name);
2007 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2008 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2009 close_file(req, fsp, ERROR_CLOSE);
2010 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2011 goto out;
2014 /* If the caller set the extended oplock request bit
2015 and we granted one (by whatever means) - set the
2016 correct bit for extended oplock reply.
2019 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2020 smb_action |= EXTENDED_OPLOCK_GRANTED;
2023 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2024 smb_action |= EXTENDED_OPLOCK_GRANTED;
2027 /* If the caller set the core oplock request bit
2028 and we granted one (by whatever means) - set the
2029 correct bit for core oplock reply.
2032 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2033 reply_outbuf(req, 19, 0);
2034 } else {
2035 reply_outbuf(req, 15, 0);
2038 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2039 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2041 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2042 SCVAL(req->outbuf, smb_flg,
2043 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2046 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2047 SCVAL(req->outbuf, smb_flg,
2048 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2051 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2052 SSVAL(req->outbuf,smb_vwv3,fattr);
2053 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2054 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2055 } else {
2056 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2058 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2059 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2060 SSVAL(req->outbuf,smb_vwv11,smb_action);
2062 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2063 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2066 out:
2067 TALLOC_FREE(smb_fname);
2068 END_PROFILE(SMBopenX);
2069 return;
2072 /****************************************************************************
2073 Reply to a SMBulogoffX.
2074 ****************************************************************************/
2076 void reply_ulogoffX(struct smb_request *req)
2078 struct smbd_server_connection *sconn = req->sconn;
2079 user_struct *vuser;
2081 START_PROFILE(SMBulogoffX);
2083 vuser = get_valid_user_struct(sconn, req->vuid);
2085 if(vuser == NULL) {
2086 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2087 req->vuid));
2089 req->vuid = UID_FIELD_INVALID;
2090 reply_force_doserror(req, ERRSRV, ERRbaduid);
2091 END_PROFILE(SMBulogoffX);
2092 return;
2095 /* in user level security we are supposed to close any files
2096 open by this user */
2097 if (vuser != NULL) {
2098 file_close_user(sconn, req->vuid);
2101 invalidate_vuid(sconn, req->vuid);
2103 reply_outbuf(req, 2, 0);
2104 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2105 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2107 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2109 END_PROFILE(SMBulogoffX);
2110 req->vuid = UID_FIELD_INVALID;
2113 /****************************************************************************
2114 Reply to a mknew or a create.
2115 ****************************************************************************/
2117 void reply_mknew(struct smb_request *req)
2119 connection_struct *conn = req->conn;
2120 struct smb_filename *smb_fname = NULL;
2121 char *fname = NULL;
2122 uint32 fattr = 0;
2123 struct smb_file_time ft;
2124 files_struct *fsp;
2125 int oplock_request = 0;
2126 NTSTATUS status;
2127 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2128 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2129 uint32 create_disposition;
2130 uint32 create_options = 0;
2131 TALLOC_CTX *ctx = talloc_tos();
2133 START_PROFILE(SMBcreate);
2134 ZERO_STRUCT(ft);
2136 if (req->wct < 3) {
2137 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2138 goto out;
2141 fattr = SVAL(req->vwv+0, 0);
2142 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2144 /* mtime. */
2145 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2147 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2148 STR_TERMINATE, &status);
2149 if (!NT_STATUS_IS_OK(status)) {
2150 reply_nterror(req, status);
2151 goto out;
2154 status = filename_convert(ctx,
2155 conn,
2156 req->flags2 & FLAGS2_DFS_PATHNAMES,
2157 fname,
2159 NULL,
2160 &smb_fname);
2161 if (!NT_STATUS_IS_OK(status)) {
2162 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2163 reply_botherror(req,
2164 NT_STATUS_PATH_NOT_COVERED,
2165 ERRSRV, ERRbadpath);
2166 goto out;
2168 reply_nterror(req, status);
2169 goto out;
2172 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2173 DEBUG(0,("Attempt to create file (%s) with volid set - "
2174 "please report this\n",
2175 smb_fname_str_dbg(smb_fname)));
2178 if(req->cmd == SMBmknew) {
2179 /* We should fail if file exists. */
2180 create_disposition = FILE_CREATE;
2181 } else {
2182 /* Create if file doesn't exist, truncate if it does. */
2183 create_disposition = FILE_OVERWRITE_IF;
2186 status = SMB_VFS_CREATE_FILE(
2187 conn, /* conn */
2188 req, /* req */
2189 0, /* root_dir_fid */
2190 smb_fname, /* fname */
2191 access_mask, /* access_mask */
2192 share_mode, /* share_access */
2193 create_disposition, /* create_disposition*/
2194 create_options, /* create_options */
2195 fattr, /* file_attributes */
2196 oplock_request, /* oplock_request */
2197 0, /* allocation_size */
2198 0, /* private_flags */
2199 NULL, /* sd */
2200 NULL, /* ea_list */
2201 &fsp, /* result */
2202 NULL); /* pinfo */
2204 if (!NT_STATUS_IS_OK(status)) {
2205 if (open_was_deferred(req->sconn, req->mid)) {
2206 /* We have re-scheduled this call. */
2207 goto out;
2209 reply_openerror(req, status);
2210 goto out;
2213 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2214 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2215 if (!NT_STATUS_IS_OK(status)) {
2216 END_PROFILE(SMBcreate);
2217 goto out;
2220 reply_outbuf(req, 1, 0);
2221 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2223 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2224 SCVAL(req->outbuf,smb_flg,
2225 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2228 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2229 SCVAL(req->outbuf,smb_flg,
2230 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2233 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2234 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2235 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2236 (unsigned int)fattr));
2238 out:
2239 TALLOC_FREE(smb_fname);
2240 END_PROFILE(SMBcreate);
2241 return;
2244 /****************************************************************************
2245 Reply to a create temporary file.
2246 ****************************************************************************/
2248 void reply_ctemp(struct smb_request *req)
2250 connection_struct *conn = req->conn;
2251 struct smb_filename *smb_fname = NULL;
2252 char *fname = NULL;
2253 uint32 fattr;
2254 files_struct *fsp;
2255 int oplock_request;
2256 int tmpfd;
2257 char *s;
2258 NTSTATUS status;
2259 TALLOC_CTX *ctx = talloc_tos();
2261 START_PROFILE(SMBctemp);
2263 if (req->wct < 3) {
2264 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2265 goto out;
2268 fattr = SVAL(req->vwv+0, 0);
2269 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2271 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2272 STR_TERMINATE, &status);
2273 if (!NT_STATUS_IS_OK(status)) {
2274 reply_nterror(req, status);
2275 goto out;
2277 if (*fname) {
2278 fname = talloc_asprintf(ctx,
2279 "%s/TMXXXXXX",
2280 fname);
2281 } else {
2282 fname = talloc_strdup(ctx, "TMXXXXXX");
2285 if (!fname) {
2286 reply_nterror(req, NT_STATUS_NO_MEMORY);
2287 goto out;
2290 status = filename_convert(ctx, conn,
2291 req->flags2 & FLAGS2_DFS_PATHNAMES,
2292 fname,
2294 NULL,
2295 &smb_fname);
2296 if (!NT_STATUS_IS_OK(status)) {
2297 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2298 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2299 ERRSRV, ERRbadpath);
2300 goto out;
2302 reply_nterror(req, status);
2303 goto out;
2306 tmpfd = mkstemp(smb_fname->base_name);
2307 if (tmpfd == -1) {
2308 reply_nterror(req, map_nt_error_from_unix(errno));
2309 goto out;
2312 SMB_VFS_STAT(conn, smb_fname);
2314 /* We should fail if file does not exist. */
2315 status = SMB_VFS_CREATE_FILE(
2316 conn, /* conn */
2317 req, /* req */
2318 0, /* root_dir_fid */
2319 smb_fname, /* fname */
2320 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2321 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2322 FILE_OPEN, /* create_disposition*/
2323 0, /* create_options */
2324 fattr, /* file_attributes */
2325 oplock_request, /* oplock_request */
2326 0, /* allocation_size */
2327 0, /* private_flags */
2328 NULL, /* sd */
2329 NULL, /* ea_list */
2330 &fsp, /* result */
2331 NULL); /* pinfo */
2333 /* close fd from mkstemp() */
2334 close(tmpfd);
2336 if (!NT_STATUS_IS_OK(status)) {
2337 if (open_was_deferred(req->sconn, req->mid)) {
2338 /* We have re-scheduled this call. */
2339 goto out;
2341 reply_openerror(req, status);
2342 goto out;
2345 reply_outbuf(req, 1, 0);
2346 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2348 /* the returned filename is relative to the directory */
2349 s = strrchr_m(fsp->fsp_name->base_name, '/');
2350 if (!s) {
2351 s = fsp->fsp_name->base_name;
2352 } else {
2353 s++;
2356 #if 0
2357 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2358 thing in the byte section. JRA */
2359 SSVALS(p, 0, -1); /* what is this? not in spec */
2360 #endif
2361 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2362 == -1) {
2363 reply_nterror(req, NT_STATUS_NO_MEMORY);
2364 goto out;
2367 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2368 SCVAL(req->outbuf, smb_flg,
2369 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2372 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2373 SCVAL(req->outbuf, smb_flg,
2374 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2377 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2378 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2379 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2380 out:
2381 TALLOC_FREE(smb_fname);
2382 END_PROFILE(SMBctemp);
2383 return;
2386 /*******************************************************************
2387 Check if a user is allowed to rename a file.
2388 ********************************************************************/
2390 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2391 uint16 dirtype)
2393 if (!CAN_WRITE(conn)) {
2394 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2397 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2398 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2399 /* Only bother to read the DOS attribute if we might deny the
2400 rename on the grounds of attribute missmatch. */
2401 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2402 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2403 return NT_STATUS_NO_SUCH_FILE;
2407 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2408 if (fsp->posix_open) {
2409 return NT_STATUS_OK;
2412 /* If no pathnames are open below this
2413 directory, allow the rename. */
2415 if (file_find_subpath(fsp)) {
2416 return NT_STATUS_ACCESS_DENIED;
2418 return NT_STATUS_OK;
2421 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2422 return NT_STATUS_OK;
2425 return NT_STATUS_ACCESS_DENIED;
2428 /*******************************************************************
2429 * unlink a file with all relevant access checks
2430 *******************************************************************/
2432 static NTSTATUS do_unlink(connection_struct *conn,
2433 struct smb_request *req,
2434 struct smb_filename *smb_fname,
2435 uint32 dirtype)
2437 uint32 fattr;
2438 files_struct *fsp;
2439 uint32 dirtype_orig = dirtype;
2440 NTSTATUS status;
2441 int ret;
2442 bool posix_paths = lp_posix_pathnames();
2444 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2445 smb_fname_str_dbg(smb_fname),
2446 dirtype));
2448 if (!CAN_WRITE(conn)) {
2449 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2452 if (posix_paths) {
2453 ret = SMB_VFS_LSTAT(conn, smb_fname);
2454 } else {
2455 ret = SMB_VFS_STAT(conn, smb_fname);
2457 if (ret != 0) {
2458 return map_nt_error_from_unix(errno);
2461 fattr = dos_mode(conn, smb_fname);
2463 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2464 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2467 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2468 if (!dirtype) {
2469 return NT_STATUS_NO_SUCH_FILE;
2472 if (!dir_check_ftype(conn, fattr, dirtype)) {
2473 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2474 return NT_STATUS_FILE_IS_A_DIRECTORY;
2476 return NT_STATUS_NO_SUCH_FILE;
2479 if (dirtype_orig & 0x8000) {
2480 /* These will never be set for POSIX. */
2481 return NT_STATUS_NO_SUCH_FILE;
2484 #if 0
2485 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2486 return NT_STATUS_FILE_IS_A_DIRECTORY;
2489 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2490 return NT_STATUS_NO_SUCH_FILE;
2493 if (dirtype & 0xFF00) {
2494 /* These will never be set for POSIX. */
2495 return NT_STATUS_NO_SUCH_FILE;
2498 dirtype &= 0xFF;
2499 if (!dirtype) {
2500 return NT_STATUS_NO_SUCH_FILE;
2503 /* Can't delete a directory. */
2504 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2505 return NT_STATUS_FILE_IS_A_DIRECTORY;
2507 #endif
2509 #if 0 /* JRATEST */
2510 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2511 return NT_STATUS_OBJECT_NAME_INVALID;
2512 #endif /* JRATEST */
2514 /* On open checks the open itself will check the share mode, so
2515 don't do it here as we'll get it wrong. */
2517 status = SMB_VFS_CREATE_FILE
2518 (conn, /* conn */
2519 req, /* req */
2520 0, /* root_dir_fid */
2521 smb_fname, /* fname */
2522 DELETE_ACCESS, /* access_mask */
2523 FILE_SHARE_NONE, /* share_access */
2524 FILE_OPEN, /* create_disposition*/
2525 FILE_NON_DIRECTORY_FILE, /* create_options */
2526 /* file_attributes */
2527 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2528 FILE_ATTRIBUTE_NORMAL,
2529 0, /* oplock_request */
2530 0, /* allocation_size */
2531 0, /* private_flags */
2532 NULL, /* sd */
2533 NULL, /* ea_list */
2534 &fsp, /* result */
2535 NULL); /* pinfo */
2537 if (!NT_STATUS_IS_OK(status)) {
2538 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2539 nt_errstr(status)));
2540 return status;
2543 status = can_set_delete_on_close(fsp, fattr);
2544 if (!NT_STATUS_IS_OK(status)) {
2545 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2546 "(%s)\n",
2547 smb_fname_str_dbg(smb_fname),
2548 nt_errstr(status)));
2549 close_file(req, fsp, NORMAL_CLOSE);
2550 return status;
2553 /* The set is across all open files on this dev/inode pair. */
2554 if (!set_delete_on_close(fsp, True,
2555 conn->session_info->security_token,
2556 conn->session_info->unix_token)) {
2557 close_file(req, fsp, NORMAL_CLOSE);
2558 return NT_STATUS_ACCESS_DENIED;
2561 return close_file(req, fsp, NORMAL_CLOSE);
2564 /****************************************************************************
2565 The guts of the unlink command, split out so it may be called by the NT SMB
2566 code.
2567 ****************************************************************************/
2569 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2570 uint32 dirtype, struct smb_filename *smb_fname,
2571 bool has_wild)
2573 char *fname_dir = NULL;
2574 char *fname_mask = NULL;
2575 int count=0;
2576 NTSTATUS status = NT_STATUS_OK;
2577 TALLOC_CTX *ctx = talloc_tos();
2579 /* Split up the directory from the filename/mask. */
2580 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2581 &fname_dir, &fname_mask);
2582 if (!NT_STATUS_IS_OK(status)) {
2583 goto out;
2587 * We should only check the mangled cache
2588 * here if unix_convert failed. This means
2589 * that the path in 'mask' doesn't exist
2590 * on the file system and so we need to look
2591 * for a possible mangle. This patch from
2592 * Tine Smukavec <valentin.smukavec@hermes.si>.
2595 if (!VALID_STAT(smb_fname->st) &&
2596 mangle_is_mangled(fname_mask, conn->params)) {
2597 char *new_mask = NULL;
2598 mangle_lookup_name_from_8_3(ctx, fname_mask,
2599 &new_mask, conn->params);
2600 if (new_mask) {
2601 TALLOC_FREE(fname_mask);
2602 fname_mask = new_mask;
2606 if (!has_wild) {
2609 * Only one file needs to be unlinked. Append the mask back
2610 * onto the directory.
2612 TALLOC_FREE(smb_fname->base_name);
2613 if (ISDOT(fname_dir)) {
2614 /* Ensure we use canonical names on open. */
2615 smb_fname->base_name = talloc_asprintf(smb_fname,
2616 "%s",
2617 fname_mask);
2618 } else {
2619 smb_fname->base_name = talloc_asprintf(smb_fname,
2620 "%s/%s",
2621 fname_dir,
2622 fname_mask);
2624 if (!smb_fname->base_name) {
2625 status = NT_STATUS_NO_MEMORY;
2626 goto out;
2628 if (dirtype == 0) {
2629 dirtype = FILE_ATTRIBUTE_NORMAL;
2632 status = check_name(conn, smb_fname->base_name);
2633 if (!NT_STATUS_IS_OK(status)) {
2634 goto out;
2637 status = do_unlink(conn, req, smb_fname, dirtype);
2638 if (!NT_STATUS_IS_OK(status)) {
2639 goto out;
2642 count++;
2643 } else {
2644 struct smb_Dir *dir_hnd = NULL;
2645 long offset = 0;
2646 const char *dname = NULL;
2647 char *talloced = NULL;
2649 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2650 status = NT_STATUS_OBJECT_NAME_INVALID;
2651 goto out;
2654 if (strequal(fname_mask,"????????.???")) {
2655 TALLOC_FREE(fname_mask);
2656 fname_mask = talloc_strdup(ctx, "*");
2657 if (!fname_mask) {
2658 status = NT_STATUS_NO_MEMORY;
2659 goto out;
2663 status = check_name(conn, fname_dir);
2664 if (!NT_STATUS_IS_OK(status)) {
2665 goto out;
2668 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2669 dirtype);
2670 if (dir_hnd == NULL) {
2671 status = map_nt_error_from_unix(errno);
2672 goto out;
2675 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2676 the pattern matches against the long name, otherwise the short name
2677 We don't implement this yet XXXX
2680 status = NT_STATUS_NO_SUCH_FILE;
2682 while ((dname = ReadDirName(dir_hnd, &offset,
2683 &smb_fname->st, &talloced))) {
2684 TALLOC_CTX *frame = talloc_stackframe();
2686 if (!is_visible_file(conn, fname_dir, dname,
2687 &smb_fname->st, true)) {
2688 TALLOC_FREE(frame);
2689 TALLOC_FREE(talloced);
2690 continue;
2693 /* Quick check for "." and ".." */
2694 if (ISDOT(dname) || ISDOTDOT(dname)) {
2695 TALLOC_FREE(frame);
2696 TALLOC_FREE(talloced);
2697 continue;
2700 if(!mask_match(dname, fname_mask,
2701 conn->case_sensitive)) {
2702 TALLOC_FREE(frame);
2703 TALLOC_FREE(talloced);
2704 continue;
2707 TALLOC_FREE(smb_fname->base_name);
2708 if (ISDOT(fname_dir)) {
2709 /* Ensure we use canonical names on open. */
2710 smb_fname->base_name =
2711 talloc_asprintf(smb_fname, "%s",
2712 dname);
2713 } else {
2714 smb_fname->base_name =
2715 talloc_asprintf(smb_fname, "%s/%s",
2716 fname_dir, dname);
2719 if (!smb_fname->base_name) {
2720 TALLOC_FREE(dir_hnd);
2721 status = NT_STATUS_NO_MEMORY;
2722 TALLOC_FREE(frame);
2723 TALLOC_FREE(talloced);
2724 goto out;
2727 status = check_name(conn, smb_fname->base_name);
2728 if (!NT_STATUS_IS_OK(status)) {
2729 TALLOC_FREE(dir_hnd);
2730 TALLOC_FREE(frame);
2731 TALLOC_FREE(talloced);
2732 goto out;
2735 status = do_unlink(conn, req, smb_fname, dirtype);
2736 if (!NT_STATUS_IS_OK(status)) {
2737 TALLOC_FREE(frame);
2738 TALLOC_FREE(talloced);
2739 continue;
2742 count++;
2743 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2744 smb_fname->base_name));
2746 TALLOC_FREE(frame);
2747 TALLOC_FREE(talloced);
2749 TALLOC_FREE(dir_hnd);
2752 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2753 status = map_nt_error_from_unix(errno);
2756 out:
2757 TALLOC_FREE(fname_dir);
2758 TALLOC_FREE(fname_mask);
2759 return status;
2762 /****************************************************************************
2763 Reply to a unlink
2764 ****************************************************************************/
2766 void reply_unlink(struct smb_request *req)
2768 connection_struct *conn = req->conn;
2769 char *name = NULL;
2770 struct smb_filename *smb_fname = NULL;
2771 uint32 dirtype;
2772 NTSTATUS status;
2773 bool path_contains_wcard = False;
2774 TALLOC_CTX *ctx = talloc_tos();
2776 START_PROFILE(SMBunlink);
2778 if (req->wct < 1) {
2779 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2780 goto out;
2783 dirtype = SVAL(req->vwv+0, 0);
2785 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2786 STR_TERMINATE, &status,
2787 &path_contains_wcard);
2788 if (!NT_STATUS_IS_OK(status)) {
2789 reply_nterror(req, status);
2790 goto out;
2793 status = filename_convert(ctx, conn,
2794 req->flags2 & FLAGS2_DFS_PATHNAMES,
2795 name,
2796 UCF_COND_ALLOW_WCARD_LCOMP,
2797 &path_contains_wcard,
2798 &smb_fname);
2799 if (!NT_STATUS_IS_OK(status)) {
2800 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2801 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2802 ERRSRV, ERRbadpath);
2803 goto out;
2805 reply_nterror(req, status);
2806 goto out;
2809 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2811 status = unlink_internals(conn, req, dirtype, smb_fname,
2812 path_contains_wcard);
2813 if (!NT_STATUS_IS_OK(status)) {
2814 if (open_was_deferred(req->sconn, req->mid)) {
2815 /* We have re-scheduled this call. */
2816 goto out;
2818 reply_nterror(req, status);
2819 goto out;
2822 reply_outbuf(req, 0, 0);
2823 out:
2824 TALLOC_FREE(smb_fname);
2825 END_PROFILE(SMBunlink);
2826 return;
2829 /****************************************************************************
2830 Fail for readbraw.
2831 ****************************************************************************/
2833 static void fail_readraw(void)
2835 const char *errstr = talloc_asprintf(talloc_tos(),
2836 "FAIL ! reply_readbraw: socket write fail (%s)",
2837 strerror(errno));
2838 if (!errstr) {
2839 errstr = "";
2841 exit_server_cleanly(errstr);
2844 /****************************************************************************
2845 Fake (read/write) sendfile. Returns -1 on read or write fail.
2846 ****************************************************************************/
2848 ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread)
2850 size_t bufsize;
2851 size_t tosend = nread;
2852 char *buf;
2854 if (nread == 0) {
2855 return 0;
2858 bufsize = MIN(nread, 65536);
2860 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2861 return -1;
2864 while (tosend > 0) {
2865 ssize_t ret;
2866 size_t cur_read;
2868 if (tosend > bufsize) {
2869 cur_read = bufsize;
2870 } else {
2871 cur_read = tosend;
2873 ret = read_file(fsp,buf,startpos,cur_read);
2874 if (ret == -1) {
2875 SAFE_FREE(buf);
2876 return -1;
2879 /* If we had a short read, fill with zeros. */
2880 if (ret < cur_read) {
2881 memset(buf + ret, '\0', cur_read - ret);
2884 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2885 != cur_read) {
2886 char addr[INET6_ADDRSTRLEN];
2888 * Try and give an error message saying what
2889 * client failed.
2891 DEBUG(0, ("write_data failed for client %s. "
2892 "Error %s\n",
2893 get_peer_addr(fsp->conn->sconn->sock, addr,
2894 sizeof(addr)),
2895 strerror(errno)));
2896 SAFE_FREE(buf);
2897 return -1;
2899 tosend -= cur_read;
2900 startpos += cur_read;
2903 SAFE_FREE(buf);
2904 return (ssize_t)nread;
2907 /****************************************************************************
2908 Deal with the case of sendfile reading less bytes from the file than
2909 requested. Fill with zeros (all we can do).
2910 ****************************************************************************/
2912 void sendfile_short_send(files_struct *fsp,
2913 ssize_t nread,
2914 size_t headersize,
2915 size_t smb_maxcnt)
2917 #define SHORT_SEND_BUFSIZE 1024
2918 if (nread < headersize) {
2919 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2920 "header for file %s (%s). Terminating\n",
2921 fsp_str_dbg(fsp), strerror(errno)));
2922 exit_server_cleanly("sendfile_short_send failed");
2925 nread -= headersize;
2927 if (nread < smb_maxcnt) {
2928 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2929 if (!buf) {
2930 exit_server_cleanly("sendfile_short_send: "
2931 "malloc failed");
2934 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2935 "with zeros !\n", fsp_str_dbg(fsp)));
2937 while (nread < smb_maxcnt) {
2939 * We asked for the real file size and told sendfile
2940 * to not go beyond the end of the file. But it can
2941 * happen that in between our fstat call and the
2942 * sendfile call the file was truncated. This is very
2943 * bad because we have already announced the larger
2944 * number of bytes to the client.
2946 * The best we can do now is to send 0-bytes, just as
2947 * a read from a hole in a sparse file would do.
2949 * This should happen rarely enough that I don't care
2950 * about efficiency here :-)
2952 size_t to_write;
2954 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2955 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2956 != to_write) {
2957 char addr[INET6_ADDRSTRLEN];
2959 * Try and give an error message saying what
2960 * client failed.
2962 DEBUG(0, ("write_data failed for client %s. "
2963 "Error %s\n",
2964 get_peer_addr(
2965 fsp->conn->sconn->sock, addr,
2966 sizeof(addr)),
2967 strerror(errno)));
2968 exit_server_cleanly("sendfile_short_send: "
2969 "write_data failed");
2971 nread += to_write;
2973 SAFE_FREE(buf);
2977 /****************************************************************************
2978 Return a readbraw error (4 bytes of zero).
2979 ****************************************************************************/
2981 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2983 char header[4];
2985 SIVAL(header,0,0);
2987 smbd_lock_socket(sconn);
2988 if (write_data(sconn->sock,header,4) != 4) {
2989 char addr[INET6_ADDRSTRLEN];
2991 * Try and give an error message saying what
2992 * client failed.
2994 DEBUG(0, ("write_data failed for client %s. "
2995 "Error %s\n",
2996 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2997 strerror(errno)));
2999 fail_readraw();
3001 smbd_unlock_socket(sconn);
3004 /****************************************************************************
3005 Use sendfile in readbraw.
3006 ****************************************************************************/
3008 static void send_file_readbraw(connection_struct *conn,
3009 struct smb_request *req,
3010 files_struct *fsp,
3011 off_t startpos,
3012 size_t nread,
3013 ssize_t mincount)
3015 struct smbd_server_connection *sconn = req->sconn;
3016 char *outbuf = NULL;
3017 ssize_t ret=0;
3020 * We can only use sendfile on a non-chained packet
3021 * but we can use on a non-oplocked file. tridge proved this
3022 * on a train in Germany :-). JRA.
3023 * reply_readbraw has already checked the length.
3026 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3027 (fsp->wcp == NULL) &&
3028 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3029 ssize_t sendfile_read = -1;
3030 char header[4];
3031 DATA_BLOB header_blob;
3033 _smb_setlen(header,nread);
3034 header_blob = data_blob_const(header, 4);
3036 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3037 &header_blob, startpos,
3038 nread);
3039 if (sendfile_read == -1) {
3040 /* Returning ENOSYS means no data at all was sent.
3041 * Do this as a normal read. */
3042 if (errno == ENOSYS) {
3043 goto normal_readbraw;
3047 * Special hack for broken Linux with no working sendfile. If we
3048 * return EINTR we sent the header but not the rest of the data.
3049 * Fake this up by doing read/write calls.
3051 if (errno == EINTR) {
3052 /* Ensure we don't do this again. */
3053 set_use_sendfile(SNUM(conn), False);
3054 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3056 if (fake_sendfile(fsp, startpos, nread) == -1) {
3057 DEBUG(0,("send_file_readbraw: "
3058 "fake_sendfile failed for "
3059 "file %s (%s).\n",
3060 fsp_str_dbg(fsp),
3061 strerror(errno)));
3062 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3064 return;
3067 DEBUG(0,("send_file_readbraw: sendfile failed for "
3068 "file %s (%s). Terminating\n",
3069 fsp_str_dbg(fsp), strerror(errno)));
3070 exit_server_cleanly("send_file_readbraw sendfile failed");
3071 } else if (sendfile_read == 0) {
3073 * Some sendfile implementations return 0 to indicate
3074 * that there was a short read, but nothing was
3075 * actually written to the socket. In this case,
3076 * fallback to the normal read path so the header gets
3077 * the correct byte count.
3079 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3080 "bytes falling back to the normal read: "
3081 "%s\n", fsp_str_dbg(fsp)));
3082 goto normal_readbraw;
3085 /* Deal with possible short send. */
3086 if (sendfile_read != 4+nread) {
3087 sendfile_short_send(fsp, sendfile_read, 4, nread);
3089 return;
3092 normal_readbraw:
3094 outbuf = talloc_array(NULL, char, nread+4);
3095 if (!outbuf) {
3096 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3097 (unsigned)(nread+4)));
3098 reply_readbraw_error(sconn);
3099 return;
3102 if (nread > 0) {
3103 ret = read_file(fsp,outbuf+4,startpos,nread);
3104 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3105 if (ret < mincount)
3106 ret = 0;
3107 #else
3108 if (ret < nread)
3109 ret = 0;
3110 #endif
3113 _smb_setlen(outbuf,ret);
3114 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3115 char addr[INET6_ADDRSTRLEN];
3117 * Try and give an error message saying what
3118 * client failed.
3120 DEBUG(0, ("write_data failed for client %s. "
3121 "Error %s\n",
3122 get_peer_addr(fsp->conn->sconn->sock, addr,
3123 sizeof(addr)),
3124 strerror(errno)));
3126 fail_readraw();
3129 TALLOC_FREE(outbuf);
3132 /****************************************************************************
3133 Reply to a readbraw (core+ protocol).
3134 ****************************************************************************/
3136 void reply_readbraw(struct smb_request *req)
3138 connection_struct *conn = req->conn;
3139 struct smbd_server_connection *sconn = req->sconn;
3140 ssize_t maxcount,mincount;
3141 size_t nread = 0;
3142 off_t startpos;
3143 files_struct *fsp;
3144 struct lock_struct lock;
3145 off_t size = 0;
3147 START_PROFILE(SMBreadbraw);
3149 if (srv_is_signing_active(sconn) ||
3150 is_encrypted_packet(sconn, req->inbuf)) {
3151 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3152 "raw reads/writes are disallowed.");
3155 if (req->wct < 8) {
3156 reply_readbraw_error(sconn);
3157 END_PROFILE(SMBreadbraw);
3158 return;
3161 if (sconn->smb1.echo_handler.trusted_fde) {
3162 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3163 "'async smb echo handler = yes'\n"));
3164 reply_readbraw_error(sconn);
3165 END_PROFILE(SMBreadbraw);
3166 return;
3170 * Special check if an oplock break has been issued
3171 * and the readraw request croses on the wire, we must
3172 * return a zero length response here.
3175 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3178 * We have to do a check_fsp by hand here, as
3179 * we must always return 4 zero bytes on error,
3180 * not a NTSTATUS.
3183 if (!fsp || !conn || conn != fsp->conn ||
3184 req->vuid != fsp->vuid ||
3185 fsp->is_directory || fsp->fh->fd == -1) {
3187 * fsp could be NULL here so use the value from the packet. JRA.
3189 DEBUG(3,("reply_readbraw: fnum %d not valid "
3190 "- cache prime?\n",
3191 (int)SVAL(req->vwv+0, 0)));
3192 reply_readbraw_error(sconn);
3193 END_PROFILE(SMBreadbraw);
3194 return;
3197 /* Do a "by hand" version of CHECK_READ. */
3198 if (!(fsp->can_read ||
3199 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3200 (fsp->access_mask & FILE_EXECUTE)))) {
3201 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3202 (int)SVAL(req->vwv+0, 0)));
3203 reply_readbraw_error(sconn);
3204 END_PROFILE(SMBreadbraw);
3205 return;
3208 flush_write_cache(fsp, READRAW_FLUSH);
3210 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3211 if(req->wct == 10) {
3213 * This is a large offset (64 bit) read.
3216 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3218 if(startpos < 0) {
3219 DEBUG(0,("reply_readbraw: negative 64 bit "
3220 "readraw offset (%.0f) !\n",
3221 (double)startpos ));
3222 reply_readbraw_error(sconn);
3223 END_PROFILE(SMBreadbraw);
3224 return;
3228 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3229 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3231 /* ensure we don't overrun the packet size */
3232 maxcount = MIN(65535,maxcount);
3234 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3235 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3236 &lock);
3238 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3239 reply_readbraw_error(sconn);
3240 END_PROFILE(SMBreadbraw);
3241 return;
3244 if (fsp_stat(fsp) == 0) {
3245 size = fsp->fsp_name->st.st_ex_size;
3248 if (startpos >= size) {
3249 nread = 0;
3250 } else {
3251 nread = MIN(maxcount,(size - startpos));
3254 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3255 if (nread < mincount)
3256 nread = 0;
3257 #endif
3259 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3260 "min=%lu nread=%lu\n",
3261 fsp->fnum, (double)startpos,
3262 (unsigned long)maxcount,
3263 (unsigned long)mincount,
3264 (unsigned long)nread ) );
3266 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3268 DEBUG(5,("reply_readbraw finished\n"));
3270 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3272 END_PROFILE(SMBreadbraw);
3273 return;
3276 #undef DBGC_CLASS
3277 #define DBGC_CLASS DBGC_LOCKING
3279 /****************************************************************************
3280 Reply to a lockread (core+ protocol).
3281 ****************************************************************************/
3283 void reply_lockread(struct smb_request *req)
3285 connection_struct *conn = req->conn;
3286 ssize_t nread = -1;
3287 char *data;
3288 off_t startpos;
3289 size_t numtoread;
3290 NTSTATUS status;
3291 files_struct *fsp;
3292 struct byte_range_lock *br_lck = NULL;
3293 char *p = NULL;
3294 struct smbd_server_connection *sconn = req->sconn;
3296 START_PROFILE(SMBlockread);
3298 if (req->wct < 5) {
3299 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3300 END_PROFILE(SMBlockread);
3301 return;
3304 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3306 if (!check_fsp(conn, req, fsp)) {
3307 END_PROFILE(SMBlockread);
3308 return;
3311 if (!CHECK_READ(fsp,req)) {
3312 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3313 END_PROFILE(SMBlockread);
3314 return;
3317 numtoread = SVAL(req->vwv+1, 0);
3318 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3320 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3322 reply_outbuf(req, 5, numtoread + 3);
3324 data = smb_buf(req->outbuf) + 3;
3327 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3328 * protocol request that predates the read/write lock concept.
3329 * Thus instead of asking for a read lock here we need to ask
3330 * for a write lock. JRA.
3331 * Note that the requested lock size is unaffected by max_recv.
3334 br_lck = do_lock(req->sconn->msg_ctx,
3335 fsp,
3336 (uint64_t)req->smbpid,
3337 (uint64_t)numtoread,
3338 (uint64_t)startpos,
3339 WRITE_LOCK,
3340 WINDOWS_LOCK,
3341 False, /* Non-blocking lock. */
3342 &status,
3343 NULL,
3344 NULL);
3345 TALLOC_FREE(br_lck);
3347 if (NT_STATUS_V(status)) {
3348 reply_nterror(req, status);
3349 END_PROFILE(SMBlockread);
3350 return;
3354 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3357 if (numtoread > sconn->smb1.negprot.max_recv) {
3358 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3359 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3360 (unsigned int)numtoread,
3361 (unsigned int)sconn->smb1.negprot.max_recv));
3362 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3364 nread = read_file(fsp,data,startpos,numtoread);
3366 if (nread < 0) {
3367 reply_nterror(req, map_nt_error_from_unix(errno));
3368 END_PROFILE(SMBlockread);
3369 return;
3372 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3374 SSVAL(req->outbuf,smb_vwv0,nread);
3375 SSVAL(req->outbuf,smb_vwv5,nread+3);
3376 p = smb_buf(req->outbuf);
3377 SCVAL(p,0,0); /* pad byte. */
3378 SSVAL(p,1,nread);
3380 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3381 fsp->fnum, (int)numtoread, (int)nread));
3383 END_PROFILE(SMBlockread);
3384 return;
3387 #undef DBGC_CLASS
3388 #define DBGC_CLASS DBGC_ALL
3390 /****************************************************************************
3391 Reply to a read.
3392 ****************************************************************************/
3394 void reply_read(struct smb_request *req)
3396 connection_struct *conn = req->conn;
3397 size_t numtoread;
3398 ssize_t nread = 0;
3399 char *data;
3400 off_t startpos;
3401 int outsize = 0;
3402 files_struct *fsp;
3403 struct lock_struct lock;
3404 struct smbd_server_connection *sconn = req->sconn;
3406 START_PROFILE(SMBread);
3408 if (req->wct < 3) {
3409 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3410 END_PROFILE(SMBread);
3411 return;
3414 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3416 if (!check_fsp(conn, req, fsp)) {
3417 END_PROFILE(SMBread);
3418 return;
3421 if (!CHECK_READ(fsp,req)) {
3422 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3423 END_PROFILE(SMBread);
3424 return;
3427 numtoread = SVAL(req->vwv+1, 0);
3428 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3430 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3433 * The requested read size cannot be greater than max_recv. JRA.
3435 if (numtoread > sconn->smb1.negprot.max_recv) {
3436 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3437 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3438 (unsigned int)numtoread,
3439 (unsigned int)sconn->smb1.negprot.max_recv));
3440 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3443 reply_outbuf(req, 5, numtoread+3);
3445 data = smb_buf(req->outbuf) + 3;
3447 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3448 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3449 &lock);
3451 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3452 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3453 END_PROFILE(SMBread);
3454 return;
3457 if (numtoread > 0)
3458 nread = read_file(fsp,data,startpos,numtoread);
3460 if (nread < 0) {
3461 reply_nterror(req, map_nt_error_from_unix(errno));
3462 goto strict_unlock;
3465 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3467 SSVAL(req->outbuf,smb_vwv0,nread);
3468 SSVAL(req->outbuf,smb_vwv5,nread+3);
3469 SCVAL(smb_buf(req->outbuf),0,1);
3470 SSVAL(smb_buf(req->outbuf),1,nread);
3472 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3473 fsp->fnum, (int)numtoread, (int)nread ) );
3475 strict_unlock:
3476 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3478 END_PROFILE(SMBread);
3479 return;
3482 /****************************************************************************
3483 Setup readX header.
3484 ****************************************************************************/
3486 static int setup_readX_header(struct smb_request *req, char *outbuf,
3487 size_t smb_maxcnt)
3489 int outsize;
3491 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
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,
3499 (smb_wct - 4) /* offset from smb header to wct */
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));
3507 return outsize;
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, off_t startpos,
3516 size_t smb_maxcnt)
3518 ssize_t nread = -1;
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));
3524 return;
3527 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3528 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3529 &lock);
3531 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3532 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3533 return;
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->sconn, req->inbuf) &&
3554 (fsp->base_fsp == NULL) &&
3555 (fsp->wcp == NULL) &&
3556 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3557 uint8 headerbuf[smb_size + 12 * 2];
3558 DATA_BLOB header;
3561 * Set up the packet header before send. We
3562 * assume here the sendfile will work (get the
3563 * correct amount of data).
3566 header = data_blob_const(headerbuf, sizeof(headerbuf));
3568 construct_reply_common_req(req, (char *)headerbuf);
3569 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3571 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3572 startpos, smb_maxcnt);
3573 if (nread == -1) {
3574 /* Returning ENOSYS means no data at all was sent.
3575 Do this as a normal read. */
3576 if (errno == ENOSYS) {
3577 goto normal_read;
3581 * Special hack for broken Linux with no working sendfile. If we
3582 * return EINTR we sent the header but not the rest of the data.
3583 * Fake this up by doing read/write calls.
3586 if (errno == EINTR) {
3587 /* Ensure we don't do this again. */
3588 set_use_sendfile(SNUM(conn), False);
3589 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3590 nread = fake_sendfile(fsp, startpos,
3591 smb_maxcnt);
3592 if (nread == -1) {
3593 DEBUG(0,("send_file_readX: "
3594 "fake_sendfile failed for "
3595 "file %s (%s).\n",
3596 fsp_str_dbg(fsp),
3597 strerror(errno)));
3598 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3600 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3601 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3602 /* No outbuf here means successful sendfile. */
3603 goto strict_unlock;
3606 DEBUG(0,("send_file_readX: sendfile failed for file "
3607 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3608 strerror(errno)));
3609 exit_server_cleanly("send_file_readX sendfile failed");
3610 } else if (nread == 0) {
3612 * Some sendfile implementations return 0 to indicate
3613 * that there was a short read, but nothing was
3614 * actually written to the socket. In this case,
3615 * fallback to the normal read path so the header gets
3616 * the correct byte count.
3618 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3619 "falling back to the normal read: %s\n",
3620 fsp_str_dbg(fsp)));
3621 goto normal_read;
3624 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3625 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3627 /* Deal with possible short send. */
3628 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3629 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3631 /* No outbuf here means successful sendfile. */
3632 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3633 SMB_PERFCOUNT_END(&req->pcd);
3634 goto strict_unlock;
3637 normal_read:
3639 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3640 uint8 headerbuf[smb_size + 2*12];
3642 construct_reply_common_req(req, (char *)headerbuf);
3643 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3645 /* Send out the header. */
3646 if (write_data(req->sconn->sock, (char *)headerbuf,
3647 sizeof(headerbuf)) != sizeof(headerbuf)) {
3649 char addr[INET6_ADDRSTRLEN];
3651 * Try and give an error message saying what
3652 * client failed.
3654 DEBUG(0, ("write_data failed for client %s. "
3655 "Error %s\n",
3656 get_peer_addr(req->sconn->sock, addr,
3657 sizeof(addr)),
3658 strerror(errno)));
3660 DEBUG(0,("send_file_readX: write_data failed for file "
3661 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3662 strerror(errno)));
3663 exit_server_cleanly("send_file_readX sendfile failed");
3665 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3666 if (nread == -1) {
3667 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3668 "file %s (%s).\n", fsp_str_dbg(fsp),
3669 strerror(errno)));
3670 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3672 goto strict_unlock;
3675 nosendfile_read:
3677 reply_outbuf(req, 12, smb_maxcnt);
3678 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3679 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3681 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3682 saved_errno = errno;
3684 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3686 if (nread < 0) {
3687 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3688 return;
3691 setup_readX_header(req, (char *)req->outbuf, nread);
3693 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3694 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3695 return;
3697 strict_unlock:
3698 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3699 TALLOC_FREE(req->outbuf);
3700 return;
3703 /****************************************************************************
3704 Reply to a read and X.
3705 ****************************************************************************/
3707 void reply_read_and_X(struct smb_request *req)
3709 struct smbd_server_connection *sconn = req->sconn;
3710 connection_struct *conn = req->conn;
3711 files_struct *fsp;
3712 off_t startpos;
3713 size_t smb_maxcnt;
3714 bool big_readX = False;
3715 #if 0
3716 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3717 #endif
3719 START_PROFILE(SMBreadX);
3721 if ((req->wct != 10) && (req->wct != 12)) {
3722 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3723 return;
3726 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3727 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3728 smb_maxcnt = SVAL(req->vwv+5, 0);
3730 /* If it's an IPC, pass off the pipe handler. */
3731 if (IS_IPC(conn)) {
3732 reply_pipe_read_and_X(req);
3733 END_PROFILE(SMBreadX);
3734 return;
3737 if (!check_fsp(conn, req, fsp)) {
3738 END_PROFILE(SMBreadX);
3739 return;
3742 if (!CHECK_READ(fsp,req)) {
3743 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3744 END_PROFILE(SMBreadX);
3745 return;
3748 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_LARGE_READ_CAP) ||
3749 (get_remote_arch() == RA_SAMBA)) {
3751 * This is Samba only behavior (up to Samba 3.6)!
3753 * Windows 2008 R2 ignores the upper_size,
3754 * so we do unless unix extentions are active
3755 * or "smbclient" is talking to us.
3757 size_t upper_size = SVAL(req->vwv+7, 0);
3758 smb_maxcnt |= (upper_size<<16);
3759 if (upper_size > 1) {
3760 /* Can't do this on a chained packet. */
3761 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3762 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3763 END_PROFILE(SMBreadX);
3764 return;
3766 /* We currently don't do this on signed or sealed data. */
3767 if (srv_is_signing_active(req->sconn) ||
3768 is_encrypted_packet(req->sconn, req->inbuf)) {
3769 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3770 END_PROFILE(SMBreadX);
3771 return;
3773 /* Is there room in the reply for this data ? */
3774 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3775 reply_nterror(req,
3776 NT_STATUS_INVALID_PARAMETER);
3777 END_PROFILE(SMBreadX);
3778 return;
3780 big_readX = True;
3784 if (req->wct == 12) {
3786 * This is a large offset (64 bit) read.
3788 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
3792 if (!big_readX) {
3793 NTSTATUS status = schedule_aio_read_and_X(conn,
3794 req,
3795 fsp,
3796 startpos,
3797 smb_maxcnt);
3798 if (NT_STATUS_IS_OK(status)) {
3799 /* Read scheduled - we're done. */
3800 goto out;
3802 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3803 /* Real error - report to client. */
3804 END_PROFILE(SMBreadX);
3805 reply_nterror(req, status);
3806 return;
3808 /* NT_STATUS_RETRY - fall back to sync read. */
3811 smbd_lock_socket(req->sconn);
3812 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3813 smbd_unlock_socket(req->sconn);
3815 out:
3816 END_PROFILE(SMBreadX);
3817 return;
3820 /****************************************************************************
3821 Error replies to writebraw must have smb_wct == 1. Fix this up.
3822 ****************************************************************************/
3824 void error_to_writebrawerr(struct smb_request *req)
3826 uint8 *old_outbuf = req->outbuf;
3828 reply_outbuf(req, 1, 0);
3830 memcpy(req->outbuf, old_outbuf, smb_size);
3831 TALLOC_FREE(old_outbuf);
3834 /****************************************************************************
3835 Read 4 bytes of a smb packet and return the smb length of the packet.
3836 Store the result in the buffer. This version of the function will
3837 never return a session keepalive (length of zero).
3838 Timeout is in milliseconds.
3839 ****************************************************************************/
3841 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3842 size_t *len)
3844 uint8_t msgtype = NBSSkeepalive;
3846 while (msgtype == NBSSkeepalive) {
3847 NTSTATUS status;
3849 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3850 len);
3851 if (!NT_STATUS_IS_OK(status)) {
3852 char addr[INET6_ADDRSTRLEN];
3853 /* Try and give an error message
3854 * saying what client failed. */
3855 DEBUG(0, ("read_fd_with_timeout failed for "
3856 "client %s read error = %s.\n",
3857 get_peer_addr(fd,addr,sizeof(addr)),
3858 nt_errstr(status)));
3859 return status;
3862 msgtype = CVAL(inbuf, 0);
3865 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3866 (unsigned long)len));
3868 return NT_STATUS_OK;
3871 /****************************************************************************
3872 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3873 ****************************************************************************/
3875 void reply_writebraw(struct smb_request *req)
3877 connection_struct *conn = req->conn;
3878 char *buf = NULL;
3879 ssize_t nwritten=0;
3880 ssize_t total_written=0;
3881 size_t numtowrite=0;
3882 size_t tcount;
3883 off_t startpos;
3884 const char *data=NULL;
3885 bool write_through;
3886 files_struct *fsp;
3887 struct lock_struct lock;
3888 NTSTATUS status;
3890 START_PROFILE(SMBwritebraw);
3893 * If we ever reply with an error, it must have the SMB command
3894 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3895 * we're finished.
3897 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3899 if (srv_is_signing_active(req->sconn)) {
3900 END_PROFILE(SMBwritebraw);
3901 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3902 "raw reads/writes are disallowed.");
3905 if (req->wct < 12) {
3906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3907 error_to_writebrawerr(req);
3908 END_PROFILE(SMBwritebraw);
3909 return;
3912 if (req->sconn->smb1.echo_handler.trusted_fde) {
3913 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3914 "'async smb echo handler = yes'\n"));
3915 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3916 error_to_writebrawerr(req);
3917 END_PROFILE(SMBwritebraw);
3918 return;
3921 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3922 if (!check_fsp(conn, req, fsp)) {
3923 error_to_writebrawerr(req);
3924 END_PROFILE(SMBwritebraw);
3925 return;
3928 if (!CHECK_WRITE(fsp)) {
3929 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3930 error_to_writebrawerr(req);
3931 END_PROFILE(SMBwritebraw);
3932 return;
3935 tcount = IVAL(req->vwv+1, 0);
3936 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3937 write_through = BITSETW(req->vwv+7,0);
3939 /* We have to deal with slightly different formats depending
3940 on whether we are using the core+ or lanman1.0 protocol */
3942 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3943 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3944 data = smb_buf_const(req->inbuf);
3945 } else {
3946 numtowrite = SVAL(req->vwv+10, 0);
3947 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3950 /* Ensure we don't write bytes past the end of this packet. */
3951 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3952 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3953 error_to_writebrawerr(req);
3954 END_PROFILE(SMBwritebraw);
3955 return;
3958 if (!fsp->print_file) {
3959 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3960 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3961 &lock);
3963 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3964 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3965 error_to_writebrawerr(req);
3966 END_PROFILE(SMBwritebraw);
3967 return;
3971 if (numtowrite>0) {
3972 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3975 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3976 "wrote=%d sync=%d\n",
3977 fsp->fnum, (double)startpos, (int)numtowrite,
3978 (int)nwritten, (int)write_through));
3980 if (nwritten < (ssize_t)numtowrite) {
3981 reply_nterror(req, NT_STATUS_DISK_FULL);
3982 error_to_writebrawerr(req);
3983 goto strict_unlock;
3986 total_written = nwritten;
3988 /* Allocate a buffer of 64k + length. */
3989 buf = talloc_array(NULL, char, 65540);
3990 if (!buf) {
3991 reply_nterror(req, NT_STATUS_NO_MEMORY);
3992 error_to_writebrawerr(req);
3993 goto strict_unlock;
3996 /* Return a SMBwritebraw message to the redirector to tell
3997 * it to send more bytes */
3999 memcpy(buf, req->inbuf, smb_size);
4000 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4001 SCVAL(buf,smb_com,SMBwritebraw);
4002 SSVALS(buf,smb_vwv0,0xFFFF);
4003 show_msg(buf);
4004 if (!srv_send_smb(req->sconn,
4005 buf,
4006 false, 0, /* no signing */
4007 IS_CONN_ENCRYPTED(conn),
4008 &req->pcd)) {
4009 exit_server_cleanly("reply_writebraw: srv_send_smb "
4010 "failed.");
4013 /* Now read the raw data into the buffer and write it */
4014 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4015 &numtowrite);
4016 if (!NT_STATUS_IS_OK(status)) {
4017 exit_server_cleanly("secondary writebraw failed");
4020 /* Set up outbuf to return the correct size */
4021 reply_outbuf(req, 1, 0);
4023 if (numtowrite != 0) {
4025 if (numtowrite > 0xFFFF) {
4026 DEBUG(0,("reply_writebraw: Oversize secondary write "
4027 "raw requested (%u). Terminating\n",
4028 (unsigned int)numtowrite ));
4029 exit_server_cleanly("secondary writebraw failed");
4032 if (tcount > nwritten+numtowrite) {
4033 DEBUG(3,("reply_writebraw: Client overestimated the "
4034 "write %d %d %d\n",
4035 (int)tcount,(int)nwritten,(int)numtowrite));
4038 status = read_data(req->sconn->sock, buf+4, numtowrite);
4040 if (!NT_STATUS_IS_OK(status)) {
4041 char addr[INET6_ADDRSTRLEN];
4042 /* Try and give an error message
4043 * saying what client failed. */
4044 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4045 "raw read failed (%s) for client %s. "
4046 "Terminating\n", nt_errstr(status),
4047 get_peer_addr(req->sconn->sock, addr,
4048 sizeof(addr))));
4049 exit_server_cleanly("secondary writebraw failed");
4052 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4053 if (nwritten == -1) {
4054 TALLOC_FREE(buf);
4055 reply_nterror(req, map_nt_error_from_unix(errno));
4056 error_to_writebrawerr(req);
4057 goto strict_unlock;
4060 if (nwritten < (ssize_t)numtowrite) {
4061 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4062 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4065 if (nwritten > 0) {
4066 total_written += nwritten;
4070 TALLOC_FREE(buf);
4071 SSVAL(req->outbuf,smb_vwv0,total_written);
4073 status = sync_file(conn, fsp, write_through);
4074 if (!NT_STATUS_IS_OK(status)) {
4075 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4076 fsp_str_dbg(fsp), nt_errstr(status)));
4077 reply_nterror(req, status);
4078 error_to_writebrawerr(req);
4079 goto strict_unlock;
4082 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4083 "wrote=%d\n",
4084 fsp->fnum, (double)startpos, (int)numtowrite,
4085 (int)total_written));
4087 if (!fsp->print_file) {
4088 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4091 /* We won't return a status if write through is not selected - this
4092 * follows what WfWg does */
4093 END_PROFILE(SMBwritebraw);
4095 if (!write_through && total_written==tcount) {
4097 #if RABBIT_PELLET_FIX
4099 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4100 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4101 * JRA.
4103 if (!send_keepalive(req->sconn->sock)) {
4104 exit_server_cleanly("reply_writebraw: send of "
4105 "keepalive failed");
4107 #endif
4108 TALLOC_FREE(req->outbuf);
4110 return;
4112 strict_unlock:
4113 if (!fsp->print_file) {
4114 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4117 END_PROFILE(SMBwritebraw);
4118 return;
4121 #undef DBGC_CLASS
4122 #define DBGC_CLASS DBGC_LOCKING
4124 /****************************************************************************
4125 Reply to a writeunlock (core+).
4126 ****************************************************************************/
4128 void reply_writeunlock(struct smb_request *req)
4130 connection_struct *conn = req->conn;
4131 ssize_t nwritten = -1;
4132 size_t numtowrite;
4133 off_t startpos;
4134 const char *data;
4135 NTSTATUS status = NT_STATUS_OK;
4136 files_struct *fsp;
4137 struct lock_struct lock;
4138 int saved_errno = 0;
4140 START_PROFILE(SMBwriteunlock);
4142 if (req->wct < 5) {
4143 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4144 END_PROFILE(SMBwriteunlock);
4145 return;
4148 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4150 if (!check_fsp(conn, req, fsp)) {
4151 END_PROFILE(SMBwriteunlock);
4152 return;
4155 if (!CHECK_WRITE(fsp)) {
4156 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4157 END_PROFILE(SMBwriteunlock);
4158 return;
4161 numtowrite = SVAL(req->vwv+1, 0);
4162 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4163 data = (const char *)req->buf + 3;
4165 if (!fsp->print_file && numtowrite > 0) {
4166 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4167 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4168 &lock);
4170 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4171 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4172 END_PROFILE(SMBwriteunlock);
4173 return;
4177 /* The special X/Open SMB protocol handling of
4178 zero length writes is *NOT* done for
4179 this call */
4180 if(numtowrite == 0) {
4181 nwritten = 0;
4182 } else {
4183 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4184 saved_errno = errno;
4187 status = sync_file(conn, fsp, False /* write through */);
4188 if (!NT_STATUS_IS_OK(status)) {
4189 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4190 fsp_str_dbg(fsp), nt_errstr(status)));
4191 reply_nterror(req, status);
4192 goto strict_unlock;
4195 if(nwritten < 0) {
4196 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4197 goto strict_unlock;
4200 if((nwritten < numtowrite) && (numtowrite != 0)) {
4201 reply_nterror(req, NT_STATUS_DISK_FULL);
4202 goto strict_unlock;
4205 if (numtowrite && !fsp->print_file) {
4206 status = do_unlock(req->sconn->msg_ctx,
4207 fsp,
4208 (uint64_t)req->smbpid,
4209 (uint64_t)numtowrite,
4210 (uint64_t)startpos,
4211 WINDOWS_LOCK);
4213 if (NT_STATUS_V(status)) {
4214 reply_nterror(req, status);
4215 goto strict_unlock;
4219 reply_outbuf(req, 1, 0);
4221 SSVAL(req->outbuf,smb_vwv0,nwritten);
4223 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4224 fsp->fnum, (int)numtowrite, (int)nwritten));
4226 strict_unlock:
4227 if (numtowrite && !fsp->print_file) {
4228 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4231 END_PROFILE(SMBwriteunlock);
4232 return;
4235 #undef DBGC_CLASS
4236 #define DBGC_CLASS DBGC_ALL
4238 /****************************************************************************
4239 Reply to a write.
4240 ****************************************************************************/
4242 void reply_write(struct smb_request *req)
4244 connection_struct *conn = req->conn;
4245 size_t numtowrite;
4246 ssize_t nwritten = -1;
4247 off_t startpos;
4248 const char *data;
4249 files_struct *fsp;
4250 struct lock_struct lock;
4251 NTSTATUS status;
4252 int saved_errno = 0;
4254 START_PROFILE(SMBwrite);
4256 if (req->wct < 5) {
4257 END_PROFILE(SMBwrite);
4258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4259 return;
4262 /* If it's an IPC, pass off the pipe handler. */
4263 if (IS_IPC(conn)) {
4264 reply_pipe_write(req);
4265 END_PROFILE(SMBwrite);
4266 return;
4269 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4271 if (!check_fsp(conn, req, fsp)) {
4272 END_PROFILE(SMBwrite);
4273 return;
4276 if (!CHECK_WRITE(fsp)) {
4277 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4278 END_PROFILE(SMBwrite);
4279 return;
4282 numtowrite = SVAL(req->vwv+1, 0);
4283 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4284 data = (const char *)req->buf + 3;
4286 if (!fsp->print_file) {
4287 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4288 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4289 &lock);
4291 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4292 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4293 END_PROFILE(SMBwrite);
4294 return;
4299 * X/Open SMB protocol says that if smb_vwv1 is
4300 * zero then the file size should be extended or
4301 * truncated to the size given in smb_vwv[2-3].
4304 if(numtowrite == 0) {
4306 * This is actually an allocate call, and set EOF. JRA.
4308 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4309 if (nwritten < 0) {
4310 reply_nterror(req, NT_STATUS_DISK_FULL);
4311 goto strict_unlock;
4313 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4314 if (nwritten < 0) {
4315 reply_nterror(req, NT_STATUS_DISK_FULL);
4316 goto strict_unlock;
4318 trigger_write_time_update_immediate(fsp);
4319 } else {
4320 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4323 status = sync_file(conn, fsp, False);
4324 if (!NT_STATUS_IS_OK(status)) {
4325 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4326 fsp_str_dbg(fsp), nt_errstr(status)));
4327 reply_nterror(req, status);
4328 goto strict_unlock;
4331 if(nwritten < 0) {
4332 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4333 goto strict_unlock;
4336 if((nwritten == 0) && (numtowrite != 0)) {
4337 reply_nterror(req, NT_STATUS_DISK_FULL);
4338 goto strict_unlock;
4341 reply_outbuf(req, 1, 0);
4343 SSVAL(req->outbuf,smb_vwv0,nwritten);
4345 if (nwritten < (ssize_t)numtowrite) {
4346 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4347 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4350 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4352 strict_unlock:
4353 if (!fsp->print_file) {
4354 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4357 END_PROFILE(SMBwrite);
4358 return;
4361 /****************************************************************************
4362 Ensure a buffer is a valid writeX for recvfile purposes.
4363 ****************************************************************************/
4365 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4366 (2*14) + /* word count (including bcc) */ \
4367 1 /* pad byte */)
4369 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4370 const uint8_t *inbuf)
4372 size_t numtowrite;
4373 connection_struct *conn = NULL;
4374 unsigned int doff = 0;
4375 size_t len = smb_len_large(inbuf);
4377 if (is_encrypted_packet(sconn, inbuf)) {
4378 /* Can't do this on encrypted
4379 * connections. */
4380 return false;
4383 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4384 return false;
4387 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4388 CVAL(inbuf,smb_wct) != 14) {
4389 DEBUG(10,("is_valid_writeX_buffer: chained or "
4390 "invalid word length.\n"));
4391 return false;
4394 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4395 if (conn == NULL) {
4396 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4397 return false;
4399 if (IS_IPC(conn)) {
4400 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4401 return false;
4403 if (IS_PRINT(conn)) {
4404 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4405 return false;
4407 doff = SVAL(inbuf,smb_vwv11);
4409 numtowrite = SVAL(inbuf,smb_vwv10);
4411 if (len > doff && len - doff > 0xFFFF) {
4412 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4415 if (numtowrite == 0) {
4416 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4417 return false;
4420 /* Ensure the sizes match up. */
4421 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4422 /* no pad byte...old smbclient :-( */
4423 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4424 (unsigned int)doff,
4425 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4426 return false;
4429 if (len - doff != numtowrite) {
4430 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4431 "len = %u, doff = %u, numtowrite = %u\n",
4432 (unsigned int)len,
4433 (unsigned int)doff,
4434 (unsigned int)numtowrite ));
4435 return false;
4438 DEBUG(10,("is_valid_writeX_buffer: true "
4439 "len = %u, doff = %u, numtowrite = %u\n",
4440 (unsigned int)len,
4441 (unsigned int)doff,
4442 (unsigned int)numtowrite ));
4444 return true;
4447 /****************************************************************************
4448 Reply to a write and X.
4449 ****************************************************************************/
4451 void reply_write_and_X(struct smb_request *req)
4453 connection_struct *conn = req->conn;
4454 files_struct *fsp;
4455 struct lock_struct lock;
4456 off_t startpos;
4457 size_t numtowrite;
4458 bool write_through;
4459 ssize_t nwritten;
4460 unsigned int smb_doff;
4461 unsigned int smblen;
4462 const char *data;
4463 NTSTATUS status;
4464 int saved_errno = 0;
4466 START_PROFILE(SMBwriteX);
4468 if ((req->wct != 12) && (req->wct != 14)) {
4469 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4470 goto out;
4473 numtowrite = SVAL(req->vwv+10, 0);
4474 smb_doff = SVAL(req->vwv+11, 0);
4475 smblen = smb_len(req->inbuf);
4477 if (req->unread_bytes > 0xFFFF ||
4478 (smblen > smb_doff &&
4479 smblen - smb_doff > 0xFFFF)) {
4480 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4483 if (req->unread_bytes) {
4484 /* Can't do a recvfile write on IPC$ */
4485 if (IS_IPC(conn)) {
4486 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4487 goto out;
4489 if (numtowrite != req->unread_bytes) {
4490 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4491 goto out;
4493 } else {
4494 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4495 smb_doff + numtowrite > smblen) {
4496 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4497 goto out;
4501 /* If it's an IPC, pass off the pipe handler. */
4502 if (IS_IPC(conn)) {
4503 if (req->unread_bytes) {
4504 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4505 goto out;
4507 reply_pipe_write_and_X(req);
4508 goto out;
4511 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4512 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4513 write_through = BITSETW(req->vwv+7,0);
4515 if (!check_fsp(conn, req, fsp)) {
4516 goto out;
4519 if (!CHECK_WRITE(fsp)) {
4520 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4521 goto out;
4524 data = smb_base(req->inbuf) + smb_doff;
4526 if(req->wct == 14) {
4528 * This is a large offset (64 bit) write.
4530 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4534 /* X/Open SMB protocol says that, unlike SMBwrite
4535 if the length is zero then NO truncation is
4536 done, just a write of zero. To truncate a file,
4537 use SMBwrite. */
4539 if(numtowrite == 0) {
4540 nwritten = 0;
4541 } else {
4542 if (req->unread_bytes == 0) {
4543 status = schedule_aio_write_and_X(conn,
4544 req,
4545 fsp,
4546 data,
4547 startpos,
4548 numtowrite);
4550 if (NT_STATUS_IS_OK(status)) {
4551 /* write scheduled - we're done. */
4552 goto out;
4554 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4555 /* Real error - report to client. */
4556 reply_nterror(req, status);
4557 goto out;
4559 /* NT_STATUS_RETRY - fall through to sync write. */
4562 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4563 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4564 &lock);
4566 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4567 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4568 goto out;
4571 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4572 saved_errno = errno;
4574 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4577 if(nwritten < 0) {
4578 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4579 goto out;
4582 if((nwritten == 0) && (numtowrite != 0)) {
4583 reply_nterror(req, NT_STATUS_DISK_FULL);
4584 goto out;
4587 reply_outbuf(req, 6, 0);
4588 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4589 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4590 SSVAL(req->outbuf,smb_vwv2,nwritten);
4591 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4593 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4594 fsp->fnum, (int)numtowrite, (int)nwritten));
4596 status = sync_file(conn, fsp, write_through);
4597 if (!NT_STATUS_IS_OK(status)) {
4598 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4599 fsp_str_dbg(fsp), nt_errstr(status)));
4600 reply_nterror(req, status);
4601 goto out;
4604 END_PROFILE(SMBwriteX);
4605 return;
4607 out:
4608 if (req->unread_bytes) {
4609 /* writeX failed. drain socket. */
4610 if (drain_socket(req->sconn->sock, req->unread_bytes) !=
4611 req->unread_bytes) {
4612 smb_panic("failed to drain pending bytes");
4614 req->unread_bytes = 0;
4617 END_PROFILE(SMBwriteX);
4618 return;
4621 /****************************************************************************
4622 Reply to a lseek.
4623 ****************************************************************************/
4625 void reply_lseek(struct smb_request *req)
4627 connection_struct *conn = req->conn;
4628 off_t startpos;
4629 off_t res= -1;
4630 int mode,umode;
4631 files_struct *fsp;
4633 START_PROFILE(SMBlseek);
4635 if (req->wct < 4) {
4636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4637 END_PROFILE(SMBlseek);
4638 return;
4641 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4643 if (!check_fsp(conn, req, fsp)) {
4644 return;
4647 flush_write_cache(fsp, SEEK_FLUSH);
4649 mode = SVAL(req->vwv+1, 0) & 3;
4650 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4651 startpos = (off_t)IVALS(req->vwv+2, 0);
4653 switch (mode) {
4654 case 0:
4655 umode = SEEK_SET;
4656 res = startpos;
4657 break;
4658 case 1:
4659 umode = SEEK_CUR;
4660 res = fsp->fh->pos + startpos;
4661 break;
4662 case 2:
4663 umode = SEEK_END;
4664 break;
4665 default:
4666 umode = SEEK_SET;
4667 res = startpos;
4668 break;
4671 if (umode == SEEK_END) {
4672 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4673 if(errno == EINVAL) {
4674 off_t current_pos = startpos;
4676 if(fsp_stat(fsp) == -1) {
4677 reply_nterror(req,
4678 map_nt_error_from_unix(errno));
4679 END_PROFILE(SMBlseek);
4680 return;
4683 current_pos += fsp->fsp_name->st.st_ex_size;
4684 if(current_pos < 0)
4685 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4689 if(res == -1) {
4690 reply_nterror(req, map_nt_error_from_unix(errno));
4691 END_PROFILE(SMBlseek);
4692 return;
4696 fsp->fh->pos = res;
4698 reply_outbuf(req, 2, 0);
4699 SIVAL(req->outbuf,smb_vwv0,res);
4701 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4702 fsp->fnum, (double)startpos, (double)res, mode));
4704 END_PROFILE(SMBlseek);
4705 return;
4708 /****************************************************************************
4709 Reply to a flush.
4710 ****************************************************************************/
4712 void reply_flush(struct smb_request *req)
4714 connection_struct *conn = req->conn;
4715 uint16 fnum;
4716 files_struct *fsp;
4718 START_PROFILE(SMBflush);
4720 if (req->wct < 1) {
4721 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4722 return;
4725 fnum = SVAL(req->vwv+0, 0);
4726 fsp = file_fsp(req, fnum);
4728 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4729 return;
4732 if (!fsp) {
4733 file_sync_all(conn);
4734 } else {
4735 NTSTATUS status = sync_file(conn, fsp, True);
4736 if (!NT_STATUS_IS_OK(status)) {
4737 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4738 fsp_str_dbg(fsp), nt_errstr(status)));
4739 reply_nterror(req, status);
4740 END_PROFILE(SMBflush);
4741 return;
4745 reply_outbuf(req, 0, 0);
4747 DEBUG(3,("flush\n"));
4748 END_PROFILE(SMBflush);
4749 return;
4752 /****************************************************************************
4753 Reply to a exit.
4754 conn POINTER CAN BE NULL HERE !
4755 ****************************************************************************/
4757 void reply_exit(struct smb_request *req)
4759 START_PROFILE(SMBexit);
4761 file_close_pid(req->sconn, req->smbpid, req->vuid);
4763 reply_outbuf(req, 0, 0);
4765 DEBUG(3,("exit\n"));
4767 END_PROFILE(SMBexit);
4768 return;
4771 /****************************************************************************
4772 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4773 ****************************************************************************/
4775 void reply_close(struct smb_request *req)
4777 connection_struct *conn = req->conn;
4778 NTSTATUS status = NT_STATUS_OK;
4779 files_struct *fsp = NULL;
4780 START_PROFILE(SMBclose);
4782 if (req->wct < 3) {
4783 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4784 END_PROFILE(SMBclose);
4785 return;
4788 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4791 * We can only use check_fsp if we know it's not a directory.
4794 if (!check_fsp_open(conn, req, fsp)) {
4795 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4796 END_PROFILE(SMBclose);
4797 return;
4800 if(fsp->is_directory) {
4802 * Special case - close NT SMB directory handle.
4804 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4805 status = close_file(req, fsp, NORMAL_CLOSE);
4806 } else {
4807 time_t t;
4809 * Close ordinary file.
4812 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4813 fsp->fh->fd, fsp->fnum,
4814 conn->num_files_open));
4817 * Take care of any time sent in the close.
4820 t = srv_make_unix_date3(req->vwv+1);
4821 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4824 * close_file() returns the unix errno if an error
4825 * was detected on close - normally this is due to
4826 * a disk full error. If not then it was probably an I/O error.
4829 status = close_file(req, fsp, NORMAL_CLOSE);
4832 if (!NT_STATUS_IS_OK(status)) {
4833 reply_nterror(req, status);
4834 END_PROFILE(SMBclose);
4835 return;
4838 reply_outbuf(req, 0, 0);
4839 END_PROFILE(SMBclose);
4840 return;
4843 /****************************************************************************
4844 Reply to a writeclose (Core+ protocol).
4845 ****************************************************************************/
4847 void reply_writeclose(struct smb_request *req)
4849 connection_struct *conn = req->conn;
4850 size_t numtowrite;
4851 ssize_t nwritten = -1;
4852 NTSTATUS close_status = NT_STATUS_OK;
4853 off_t startpos;
4854 const char *data;
4855 struct timespec mtime;
4856 files_struct *fsp;
4857 struct lock_struct lock;
4859 START_PROFILE(SMBwriteclose);
4861 if (req->wct < 6) {
4862 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4863 END_PROFILE(SMBwriteclose);
4864 return;
4867 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4869 if (!check_fsp(conn, req, fsp)) {
4870 END_PROFILE(SMBwriteclose);
4871 return;
4873 if (!CHECK_WRITE(fsp)) {
4874 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4875 END_PROFILE(SMBwriteclose);
4876 return;
4879 numtowrite = SVAL(req->vwv+1, 0);
4880 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4881 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4882 data = (const char *)req->buf + 1;
4884 if (!fsp->print_file) {
4885 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4886 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4887 &lock);
4889 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4890 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4891 END_PROFILE(SMBwriteclose);
4892 return;
4896 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4898 set_close_write_time(fsp, mtime);
4901 * More insanity. W2K only closes the file if writelen > 0.
4902 * JRA.
4905 if (numtowrite) {
4906 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4907 "file %s\n", fsp_str_dbg(fsp)));
4908 close_status = close_file(req, fsp, NORMAL_CLOSE);
4911 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4912 fsp->fnum, (int)numtowrite, (int)nwritten,
4913 conn->num_files_open));
4915 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4916 reply_nterror(req, NT_STATUS_DISK_FULL);
4917 goto strict_unlock;
4920 if(!NT_STATUS_IS_OK(close_status)) {
4921 reply_nterror(req, close_status);
4922 goto strict_unlock;
4925 reply_outbuf(req, 1, 0);
4927 SSVAL(req->outbuf,smb_vwv0,nwritten);
4929 strict_unlock:
4930 if (numtowrite && !fsp->print_file) {
4931 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4934 END_PROFILE(SMBwriteclose);
4935 return;
4938 #undef DBGC_CLASS
4939 #define DBGC_CLASS DBGC_LOCKING
4941 /****************************************************************************
4942 Reply to a lock.
4943 ****************************************************************************/
4945 void reply_lock(struct smb_request *req)
4947 connection_struct *conn = req->conn;
4948 uint64_t count,offset;
4949 NTSTATUS status;
4950 files_struct *fsp;
4951 struct byte_range_lock *br_lck = NULL;
4953 START_PROFILE(SMBlock);
4955 if (req->wct < 5) {
4956 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4957 END_PROFILE(SMBlock);
4958 return;
4961 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4963 if (!check_fsp(conn, req, fsp)) {
4964 END_PROFILE(SMBlock);
4965 return;
4968 count = (uint64_t)IVAL(req->vwv+1, 0);
4969 offset = (uint64_t)IVAL(req->vwv+3, 0);
4971 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4972 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4974 br_lck = do_lock(req->sconn->msg_ctx,
4975 fsp,
4976 (uint64_t)req->smbpid,
4977 count,
4978 offset,
4979 WRITE_LOCK,
4980 WINDOWS_LOCK,
4981 False, /* Non-blocking lock. */
4982 &status,
4983 NULL,
4984 NULL);
4986 TALLOC_FREE(br_lck);
4988 if (NT_STATUS_V(status)) {
4989 reply_nterror(req, status);
4990 END_PROFILE(SMBlock);
4991 return;
4994 reply_outbuf(req, 0, 0);
4996 END_PROFILE(SMBlock);
4997 return;
5000 /****************************************************************************
5001 Reply to a unlock.
5002 ****************************************************************************/
5004 void reply_unlock(struct smb_request *req)
5006 connection_struct *conn = req->conn;
5007 uint64_t count,offset;
5008 NTSTATUS status;
5009 files_struct *fsp;
5011 START_PROFILE(SMBunlock);
5013 if (req->wct < 5) {
5014 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5015 END_PROFILE(SMBunlock);
5016 return;
5019 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5021 if (!check_fsp(conn, req, fsp)) {
5022 END_PROFILE(SMBunlock);
5023 return;
5026 count = (uint64_t)IVAL(req->vwv+1, 0);
5027 offset = (uint64_t)IVAL(req->vwv+3, 0);
5029 status = do_unlock(req->sconn->msg_ctx,
5030 fsp,
5031 (uint64_t)req->smbpid,
5032 count,
5033 offset,
5034 WINDOWS_LOCK);
5036 if (NT_STATUS_V(status)) {
5037 reply_nterror(req, status);
5038 END_PROFILE(SMBunlock);
5039 return;
5042 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5043 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5045 reply_outbuf(req, 0, 0);
5047 END_PROFILE(SMBunlock);
5048 return;
5051 #undef DBGC_CLASS
5052 #define DBGC_CLASS DBGC_ALL
5054 /****************************************************************************
5055 Reply to a tdis.
5056 conn POINTER CAN BE NULL HERE !
5057 ****************************************************************************/
5059 void reply_tdis(struct smb_request *req)
5061 connection_struct *conn = req->conn;
5062 START_PROFILE(SMBtdis);
5064 if (!conn) {
5065 DEBUG(4,("Invalid connection in tdis\n"));
5066 reply_force_doserror(req, ERRSRV, ERRinvnid);
5067 END_PROFILE(SMBtdis);
5068 return;
5071 close_cnum(conn,req->vuid);
5072 req->conn = NULL;
5074 reply_outbuf(req, 0, 0);
5075 END_PROFILE(SMBtdis);
5076 return;
5079 /****************************************************************************
5080 Reply to a echo.
5081 conn POINTER CAN BE NULL HERE !
5082 ****************************************************************************/
5084 void reply_echo(struct smb_request *req)
5086 connection_struct *conn = req->conn;
5087 struct smb_perfcount_data local_pcd;
5088 struct smb_perfcount_data *cur_pcd;
5089 int smb_reverb;
5090 int seq_num;
5092 START_PROFILE(SMBecho);
5094 smb_init_perfcount_data(&local_pcd);
5096 if (req->wct < 1) {
5097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5098 END_PROFILE(SMBecho);
5099 return;
5102 smb_reverb = SVAL(req->vwv+0, 0);
5104 reply_outbuf(req, 1, req->buflen);
5106 /* copy any incoming data back out */
5107 if (req->buflen > 0) {
5108 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5111 if (smb_reverb > 100) {
5112 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5113 smb_reverb = 100;
5116 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5118 /* this makes sure we catch the request pcd */
5119 if (seq_num == smb_reverb) {
5120 cur_pcd = &req->pcd;
5121 } else {
5122 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5123 cur_pcd = &local_pcd;
5126 SSVAL(req->outbuf,smb_vwv0,seq_num);
5128 show_msg((char *)req->outbuf);
5129 if (!srv_send_smb(req->sconn,
5130 (char *)req->outbuf,
5131 true, req->seqnum+1,
5132 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5133 cur_pcd))
5134 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5137 DEBUG(3,("echo %d times\n", smb_reverb));
5139 TALLOC_FREE(req->outbuf);
5141 END_PROFILE(SMBecho);
5142 return;
5145 /****************************************************************************
5146 Reply to a printopen.
5147 ****************************************************************************/
5149 void reply_printopen(struct smb_request *req)
5151 connection_struct *conn = req->conn;
5152 files_struct *fsp;
5153 NTSTATUS status;
5155 START_PROFILE(SMBsplopen);
5157 if (req->wct < 2) {
5158 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5159 END_PROFILE(SMBsplopen);
5160 return;
5163 if (!CAN_PRINT(conn)) {
5164 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5165 END_PROFILE(SMBsplopen);
5166 return;
5169 status = file_new(req, conn, &fsp);
5170 if(!NT_STATUS_IS_OK(status)) {
5171 reply_nterror(req, status);
5172 END_PROFILE(SMBsplopen);
5173 return;
5176 /* Open for exclusive use, write only. */
5177 status = print_spool_open(fsp, NULL, req->vuid);
5179 if (!NT_STATUS_IS_OK(status)) {
5180 file_free(req, fsp);
5181 reply_nterror(req, status);
5182 END_PROFILE(SMBsplopen);
5183 return;
5186 reply_outbuf(req, 1, 0);
5187 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5189 DEBUG(3,("openprint fd=%d fnum=%d\n",
5190 fsp->fh->fd, fsp->fnum));
5192 END_PROFILE(SMBsplopen);
5193 return;
5196 /****************************************************************************
5197 Reply to a printclose.
5198 ****************************************************************************/
5200 void reply_printclose(struct smb_request *req)
5202 connection_struct *conn = req->conn;
5203 files_struct *fsp;
5204 NTSTATUS status;
5206 START_PROFILE(SMBsplclose);
5208 if (req->wct < 1) {
5209 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5210 END_PROFILE(SMBsplclose);
5211 return;
5214 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5216 if (!check_fsp(conn, req, fsp)) {
5217 END_PROFILE(SMBsplclose);
5218 return;
5221 if (!CAN_PRINT(conn)) {
5222 reply_force_doserror(req, ERRSRV, ERRerror);
5223 END_PROFILE(SMBsplclose);
5224 return;
5227 DEBUG(3,("printclose fd=%d fnum=%d\n",
5228 fsp->fh->fd,fsp->fnum));
5230 status = close_file(req, fsp, NORMAL_CLOSE);
5232 if(!NT_STATUS_IS_OK(status)) {
5233 reply_nterror(req, status);
5234 END_PROFILE(SMBsplclose);
5235 return;
5238 reply_outbuf(req, 0, 0);
5240 END_PROFILE(SMBsplclose);
5241 return;
5244 /****************************************************************************
5245 Reply to a printqueue.
5246 ****************************************************************************/
5248 void reply_printqueue(struct smb_request *req)
5250 connection_struct *conn = req->conn;
5251 int max_count;
5252 int start_index;
5254 START_PROFILE(SMBsplretq);
5256 if (req->wct < 2) {
5257 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5258 END_PROFILE(SMBsplretq);
5259 return;
5262 max_count = SVAL(req->vwv+0, 0);
5263 start_index = SVAL(req->vwv+1, 0);
5265 /* we used to allow the client to get the cnum wrong, but that
5266 is really quite gross and only worked when there was only
5267 one printer - I think we should now only accept it if they
5268 get it right (tridge) */
5269 if (!CAN_PRINT(conn)) {
5270 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5271 END_PROFILE(SMBsplretq);
5272 return;
5275 reply_outbuf(req, 2, 3);
5276 SSVAL(req->outbuf,smb_vwv0,0);
5277 SSVAL(req->outbuf,smb_vwv1,0);
5278 SCVAL(smb_buf(req->outbuf),0,1);
5279 SSVAL(smb_buf(req->outbuf),1,0);
5281 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5282 start_index, max_count));
5285 TALLOC_CTX *mem_ctx = talloc_tos();
5286 NTSTATUS status;
5287 WERROR werr;
5288 const char *sharename = lp_servicename(SNUM(conn));
5289 struct rpc_pipe_client *cli = NULL;
5290 struct dcerpc_binding_handle *b = NULL;
5291 struct policy_handle handle;
5292 struct spoolss_DevmodeContainer devmode_ctr;
5293 union spoolss_JobInfo *info;
5294 uint32_t count;
5295 uint32_t num_to_get;
5296 uint32_t first;
5297 uint32_t i;
5299 ZERO_STRUCT(handle);
5301 status = rpc_pipe_open_interface(conn,
5302 &ndr_table_spoolss.syntax_id,
5303 conn->session_info,
5304 conn->sconn->remote_address,
5305 conn->sconn->msg_ctx,
5306 &cli);
5307 if (!NT_STATUS_IS_OK(status)) {
5308 DEBUG(0, ("reply_printqueue: "
5309 "could not connect to spoolss: %s\n",
5310 nt_errstr(status)));
5311 reply_nterror(req, status);
5312 goto out;
5314 b = cli->binding_handle;
5316 ZERO_STRUCT(devmode_ctr);
5318 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5319 sharename,
5320 NULL, devmode_ctr,
5321 SEC_FLAG_MAXIMUM_ALLOWED,
5322 &handle,
5323 &werr);
5324 if (!NT_STATUS_IS_OK(status)) {
5325 reply_nterror(req, status);
5326 goto out;
5328 if (!W_ERROR_IS_OK(werr)) {
5329 reply_nterror(req, werror_to_ntstatus(werr));
5330 goto out;
5333 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5334 &handle,
5335 0, /* firstjob */
5336 0xff, /* numjobs */
5337 2, /* level */
5338 0, /* offered */
5339 &count,
5340 &info);
5341 if (!W_ERROR_IS_OK(werr)) {
5342 reply_nterror(req, werror_to_ntstatus(werr));
5343 goto out;
5346 if (max_count > 0) {
5347 first = start_index;
5348 } else {
5349 first = start_index + max_count + 1;
5352 if (first >= count) {
5353 num_to_get = first;
5354 } else {
5355 num_to_get = first + MIN(ABS(max_count), count - first);
5358 for (i = first; i < num_to_get; i++) {
5359 char blob[28];
5360 char *p = blob;
5361 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5362 int qstatus;
5363 uint16_t qrapjobid = pjobid_to_rap(sharename,
5364 info[i].info2.job_id);
5366 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5367 qstatus = 2;
5368 } else {
5369 qstatus = 3;
5372 srv_put_dos_date2(p, 0, qtime);
5373 SCVAL(p, 4, qstatus);
5374 SSVAL(p, 5, qrapjobid);
5375 SIVAL(p, 7, info[i].info2.size);
5376 SCVAL(p, 11, 0);
5377 srvstr_push(blob, req->flags2, p+12,
5378 info[i].info2.notify_name, 16, STR_ASCII);
5380 if (message_push_blob(
5381 &req->outbuf,
5382 data_blob_const(
5383 blob, sizeof(blob))) == -1) {
5384 reply_nterror(req, NT_STATUS_NO_MEMORY);
5385 goto out;
5389 if (count > 0) {
5390 SSVAL(req->outbuf,smb_vwv0,count);
5391 SSVAL(req->outbuf,smb_vwv1,
5392 (max_count>0?first+count:first-1));
5393 SCVAL(smb_buf(req->outbuf),0,1);
5394 SSVAL(smb_buf(req->outbuf),1,28*count);
5398 DEBUG(3, ("%u entries returned in queue\n",
5399 (unsigned)count));
5401 out:
5402 if (b && is_valid_policy_hnd(&handle)) {
5403 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5408 END_PROFILE(SMBsplretq);
5409 return;
5412 /****************************************************************************
5413 Reply to a printwrite.
5414 ****************************************************************************/
5416 void reply_printwrite(struct smb_request *req)
5418 connection_struct *conn = req->conn;
5419 int numtowrite;
5420 const char *data;
5421 files_struct *fsp;
5423 START_PROFILE(SMBsplwr);
5425 if (req->wct < 1) {
5426 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5427 END_PROFILE(SMBsplwr);
5428 return;
5431 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5433 if (!check_fsp(conn, req, fsp)) {
5434 END_PROFILE(SMBsplwr);
5435 return;
5438 if (!fsp->print_file) {
5439 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5440 END_PROFILE(SMBsplwr);
5441 return;
5444 if (!CHECK_WRITE(fsp)) {
5445 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5446 END_PROFILE(SMBsplwr);
5447 return;
5450 numtowrite = SVAL(req->buf, 1);
5452 if (req->buflen < numtowrite + 3) {
5453 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5454 END_PROFILE(SMBsplwr);
5455 return;
5458 data = (const char *)req->buf + 3;
5460 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5461 reply_nterror(req, map_nt_error_from_unix(errno));
5462 END_PROFILE(SMBsplwr);
5463 return;
5466 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5468 END_PROFILE(SMBsplwr);
5469 return;
5472 /****************************************************************************
5473 Reply to a mkdir.
5474 ****************************************************************************/
5476 void reply_mkdir(struct smb_request *req)
5478 connection_struct *conn = req->conn;
5479 struct smb_filename *smb_dname = NULL;
5480 char *directory = NULL;
5481 NTSTATUS status;
5482 TALLOC_CTX *ctx = talloc_tos();
5484 START_PROFILE(SMBmkdir);
5486 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5487 STR_TERMINATE, &status);
5488 if (!NT_STATUS_IS_OK(status)) {
5489 reply_nterror(req, status);
5490 goto out;
5493 status = filename_convert(ctx, conn,
5494 req->flags2 & FLAGS2_DFS_PATHNAMES,
5495 directory,
5497 NULL,
5498 &smb_dname);
5499 if (!NT_STATUS_IS_OK(status)) {
5500 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5501 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5502 ERRSRV, ERRbadpath);
5503 goto out;
5505 reply_nterror(req, status);
5506 goto out;
5509 status = create_directory(conn, req, smb_dname);
5511 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5513 if (!NT_STATUS_IS_OK(status)) {
5515 if (!use_nt_status()
5516 && NT_STATUS_EQUAL(status,
5517 NT_STATUS_OBJECT_NAME_COLLISION)) {
5519 * Yes, in the DOS error code case we get a
5520 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5521 * samba4 torture test.
5523 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5526 reply_nterror(req, status);
5527 goto out;
5530 reply_outbuf(req, 0, 0);
5532 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5533 out:
5534 TALLOC_FREE(smb_dname);
5535 END_PROFILE(SMBmkdir);
5536 return;
5539 /****************************************************************************
5540 Reply to a rmdir.
5541 ****************************************************************************/
5543 void reply_rmdir(struct smb_request *req)
5545 connection_struct *conn = req->conn;
5546 struct smb_filename *smb_dname = NULL;
5547 char *directory = NULL;
5548 NTSTATUS status;
5549 TALLOC_CTX *ctx = talloc_tos();
5550 files_struct *fsp = NULL;
5551 int info = 0;
5552 struct smbd_server_connection *sconn = req->sconn;
5554 START_PROFILE(SMBrmdir);
5556 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5557 STR_TERMINATE, &status);
5558 if (!NT_STATUS_IS_OK(status)) {
5559 reply_nterror(req, status);
5560 goto out;
5563 status = filename_convert(ctx, conn,
5564 req->flags2 & FLAGS2_DFS_PATHNAMES,
5565 directory,
5567 NULL,
5568 &smb_dname);
5569 if (!NT_STATUS_IS_OK(status)) {
5570 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5571 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5572 ERRSRV, ERRbadpath);
5573 goto out;
5575 reply_nterror(req, status);
5576 goto out;
5579 if (is_ntfs_stream_smb_fname(smb_dname)) {
5580 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5581 goto out;
5584 status = SMB_VFS_CREATE_FILE(
5585 conn, /* conn */
5586 req, /* req */
5587 0, /* root_dir_fid */
5588 smb_dname, /* fname */
5589 DELETE_ACCESS, /* access_mask */
5590 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5591 FILE_SHARE_DELETE),
5592 FILE_OPEN, /* create_disposition*/
5593 FILE_DIRECTORY_FILE, /* create_options */
5594 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5595 0, /* oplock_request */
5596 0, /* allocation_size */
5597 0, /* private_flags */
5598 NULL, /* sd */
5599 NULL, /* ea_list */
5600 &fsp, /* result */
5601 &info); /* pinfo */
5603 if (!NT_STATUS_IS_OK(status)) {
5604 if (open_was_deferred(req->sconn, req->mid)) {
5605 /* We have re-scheduled this call. */
5606 goto out;
5608 reply_nterror(req, status);
5609 goto out;
5612 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5613 if (!NT_STATUS_IS_OK(status)) {
5614 close_file(req, fsp, ERROR_CLOSE);
5615 reply_nterror(req, status);
5616 goto out;
5619 if (!set_delete_on_close(fsp, true,
5620 conn->session_info->security_token,
5621 conn->session_info->unix_token)) {
5622 close_file(req, fsp, ERROR_CLOSE);
5623 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5624 goto out;
5627 status = close_file(req, fsp, NORMAL_CLOSE);
5628 if (!NT_STATUS_IS_OK(status)) {
5629 reply_nterror(req, status);
5630 } else {
5631 reply_outbuf(req, 0, 0);
5634 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5636 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5637 out:
5638 TALLOC_FREE(smb_dname);
5639 END_PROFILE(SMBrmdir);
5640 return;
5643 /*******************************************************************
5644 Resolve wildcards in a filename rename.
5645 ********************************************************************/
5647 static bool resolve_wildcards(TALLOC_CTX *ctx,
5648 const char *name1,
5649 const char *name2,
5650 char **pp_newname)
5652 char *name2_copy = NULL;
5653 char *root1 = NULL;
5654 char *root2 = NULL;
5655 char *ext1 = NULL;
5656 char *ext2 = NULL;
5657 char *p,*p2, *pname1, *pname2;
5659 name2_copy = talloc_strdup(ctx, name2);
5660 if (!name2_copy) {
5661 return False;
5664 pname1 = strrchr_m(name1,'/');
5665 pname2 = strrchr_m(name2_copy,'/');
5667 if (!pname1 || !pname2) {
5668 return False;
5671 /* Truncate the copy of name2 at the last '/' */
5672 *pname2 = '\0';
5674 /* Now go past the '/' */
5675 pname1++;
5676 pname2++;
5678 root1 = talloc_strdup(ctx, pname1);
5679 root2 = talloc_strdup(ctx, pname2);
5681 if (!root1 || !root2) {
5682 return False;
5685 p = strrchr_m(root1,'.');
5686 if (p) {
5687 *p = 0;
5688 ext1 = talloc_strdup(ctx, p+1);
5689 } else {
5690 ext1 = talloc_strdup(ctx, "");
5692 p = strrchr_m(root2,'.');
5693 if (p) {
5694 *p = 0;
5695 ext2 = talloc_strdup(ctx, p+1);
5696 } else {
5697 ext2 = talloc_strdup(ctx, "");
5700 if (!ext1 || !ext2) {
5701 return False;
5704 p = root1;
5705 p2 = root2;
5706 while (*p2) {
5707 if (*p2 == '?') {
5708 /* Hmmm. Should this be mb-aware ? */
5709 *p2 = *p;
5710 p2++;
5711 } else if (*p2 == '*') {
5712 *p2 = '\0';
5713 root2 = talloc_asprintf(ctx, "%s%s",
5714 root2,
5716 if (!root2) {
5717 return False;
5719 break;
5720 } else {
5721 p2++;
5723 if (*p) {
5724 p++;
5728 p = ext1;
5729 p2 = ext2;
5730 while (*p2) {
5731 if (*p2 == '?') {
5732 /* Hmmm. Should this be mb-aware ? */
5733 *p2 = *p;
5734 p2++;
5735 } else if (*p2 == '*') {
5736 *p2 = '\0';
5737 ext2 = talloc_asprintf(ctx, "%s%s",
5738 ext2,
5740 if (!ext2) {
5741 return False;
5743 break;
5744 } else {
5745 p2++;
5747 if (*p) {
5748 p++;
5752 if (*ext2) {
5753 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5754 name2_copy,
5755 root2,
5756 ext2);
5757 } else {
5758 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5759 name2_copy,
5760 root2);
5763 if (!*pp_newname) {
5764 return False;
5767 return True;
5770 /****************************************************************************
5771 Ensure open files have their names updated. Updated to notify other smbd's
5772 asynchronously.
5773 ****************************************************************************/
5775 static void rename_open_files(connection_struct *conn,
5776 struct share_mode_lock *lck,
5777 uint32_t orig_name_hash,
5778 const struct smb_filename *smb_fname_dst)
5780 files_struct *fsp;
5781 bool did_rename = False;
5782 NTSTATUS status;
5783 uint32_t new_name_hash = 0;
5785 for(fsp = file_find_di_first(conn->sconn, lck->data->id); fsp;
5786 fsp = file_find_di_next(fsp)) {
5787 /* fsp_name is a relative path under the fsp. To change this for other
5788 sharepaths we need to manipulate relative paths. */
5789 /* TODO - create the absolute path and manipulate the newname
5790 relative to the sharepath. */
5791 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5792 continue;
5794 if (fsp->name_hash != orig_name_hash) {
5795 continue;
5797 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5798 "(file_id %s) from %s -> %s\n", fsp->fnum,
5799 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5800 smb_fname_str_dbg(smb_fname_dst)));
5802 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5803 if (NT_STATUS_IS_OK(status)) {
5804 did_rename = True;
5805 new_name_hash = fsp->name_hash;
5809 if (!did_rename) {
5810 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5811 "for %s\n", file_id_string_tos(&lck->data->id),
5812 smb_fname_str_dbg(smb_fname_dst)));
5815 /* Send messages to all smbd's (not ourself) that the name has changed. */
5816 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5817 orig_name_hash, new_name_hash,
5818 smb_fname_dst);
5822 /****************************************************************************
5823 We need to check if the source path is a parent directory of the destination
5824 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5825 refuse the rename with a sharing violation. Under UNIX the above call can
5826 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5827 probably need to check that the client is a Windows one before disallowing
5828 this as a UNIX client (one with UNIX extensions) can know the source is a
5829 symlink and make this decision intelligently. Found by an excellent bug
5830 report from <AndyLiebman@aol.com>.
5831 ****************************************************************************/
5833 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5834 const struct smb_filename *smb_fname_dst)
5836 const char *psrc = smb_fname_src->base_name;
5837 const char *pdst = smb_fname_dst->base_name;
5838 size_t slen;
5840 if (psrc[0] == '.' && psrc[1] == '/') {
5841 psrc += 2;
5843 if (pdst[0] == '.' && pdst[1] == '/') {
5844 pdst += 2;
5846 if ((slen = strlen(psrc)) > strlen(pdst)) {
5847 return False;
5849 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5853 * Do the notify calls from a rename
5856 static void notify_rename(connection_struct *conn, bool is_dir,
5857 const struct smb_filename *smb_fname_src,
5858 const struct smb_filename *smb_fname_dst)
5860 char *parent_dir_src = NULL;
5861 char *parent_dir_dst = NULL;
5862 uint32 mask;
5864 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5865 : FILE_NOTIFY_CHANGE_FILE_NAME;
5867 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5868 &parent_dir_src, NULL) ||
5869 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5870 &parent_dir_dst, NULL)) {
5871 goto out;
5874 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5875 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5876 smb_fname_src->base_name);
5877 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5878 smb_fname_dst->base_name);
5880 else {
5881 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5882 smb_fname_src->base_name);
5883 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5884 smb_fname_dst->base_name);
5887 /* this is a strange one. w2k3 gives an additional event for
5888 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5889 files, but not directories */
5890 if (!is_dir) {
5891 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5892 FILE_NOTIFY_CHANGE_ATTRIBUTES
5893 |FILE_NOTIFY_CHANGE_CREATION,
5894 smb_fname_dst->base_name);
5896 out:
5897 TALLOC_FREE(parent_dir_src);
5898 TALLOC_FREE(parent_dir_dst);
5901 /****************************************************************************
5902 Returns an error if the parent directory for a filename is open in an
5903 incompatible way.
5904 ****************************************************************************/
5906 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
5907 const struct smb_filename *smb_fname_dst_in)
5909 char *parent_dir = NULL;
5910 struct smb_filename smb_fname_parent;
5911 struct file_id id;
5912 files_struct *fsp = NULL;
5913 int ret;
5915 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
5916 &parent_dir, NULL)) {
5917 return NT_STATUS_NO_MEMORY;
5919 ZERO_STRUCT(smb_fname_parent);
5920 smb_fname_parent.base_name = parent_dir;
5922 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
5923 if (ret == -1) {
5924 return map_nt_error_from_unix(errno);
5928 * We're only checking on this smbd here, mostly good
5929 * enough.. and will pass tests.
5932 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
5933 for (fsp = file_find_di_first(conn->sconn, id); fsp;
5934 fsp = file_find_di_next(fsp)) {
5935 if (fsp->access_mask & DELETE_ACCESS) {
5936 return NT_STATUS_SHARING_VIOLATION;
5939 return NT_STATUS_OK;
5942 /****************************************************************************
5943 Rename an open file - given an fsp.
5944 ****************************************************************************/
5946 NTSTATUS rename_internals_fsp(connection_struct *conn,
5947 files_struct *fsp,
5948 const struct smb_filename *smb_fname_dst_in,
5949 uint32 attrs,
5950 bool replace_if_exists)
5952 TALLOC_CTX *ctx = talloc_tos();
5953 struct smb_filename *smb_fname_dst = NULL;
5954 NTSTATUS status = NT_STATUS_OK;
5955 struct share_mode_lock *lck = NULL;
5956 bool dst_exists, old_is_stream, new_is_stream;
5958 status = check_name(conn, smb_fname_dst_in->base_name);
5959 if (!NT_STATUS_IS_OK(status)) {
5960 return status;
5963 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
5964 if (!NT_STATUS_IS_OK(status)) {
5965 return status;
5968 /* Make a copy of the dst smb_fname structs */
5970 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5971 if (!NT_STATUS_IS_OK(status)) {
5972 goto out;
5976 * Check for special case with case preserving and not
5977 * case sensitive. If the old last component differs from the original
5978 * last component only by case, then we should allow
5979 * the rename (user is trying to change the case of the
5980 * filename).
5982 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5983 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5984 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5985 char *last_slash;
5986 char *fname_dst_lcomp_base_mod = NULL;
5987 struct smb_filename *smb_fname_orig_lcomp = NULL;
5990 * Get the last component of the destination name.
5992 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5993 if (last_slash) {
5994 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5995 } else {
5996 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
5998 if (!fname_dst_lcomp_base_mod) {
5999 status = NT_STATUS_NO_MEMORY;
6000 goto out;
6004 * Create an smb_filename struct using the original last
6005 * component of the destination.
6007 status = create_synthetic_smb_fname_split(ctx,
6008 smb_fname_dst->original_lcomp, NULL,
6009 &smb_fname_orig_lcomp);
6010 if (!NT_STATUS_IS_OK(status)) {
6011 TALLOC_FREE(fname_dst_lcomp_base_mod);
6012 goto out;
6015 /* If the base names only differ by case, use original. */
6016 if(!strcsequal(fname_dst_lcomp_base_mod,
6017 smb_fname_orig_lcomp->base_name)) {
6018 char *tmp;
6020 * Replace the modified last component with the
6021 * original.
6023 if (last_slash) {
6024 *last_slash = '\0'; /* Truncate at the '/' */
6025 tmp = talloc_asprintf(smb_fname_dst,
6026 "%s/%s",
6027 smb_fname_dst->base_name,
6028 smb_fname_orig_lcomp->base_name);
6029 } else {
6030 tmp = talloc_asprintf(smb_fname_dst,
6031 "%s",
6032 smb_fname_orig_lcomp->base_name);
6034 if (tmp == NULL) {
6035 status = NT_STATUS_NO_MEMORY;
6036 TALLOC_FREE(fname_dst_lcomp_base_mod);
6037 TALLOC_FREE(smb_fname_orig_lcomp);
6038 goto out;
6040 TALLOC_FREE(smb_fname_dst->base_name);
6041 smb_fname_dst->base_name = tmp;
6044 /* If the stream_names only differ by case, use original. */
6045 if(!strcsequal(smb_fname_dst->stream_name,
6046 smb_fname_orig_lcomp->stream_name)) {
6047 char *tmp = NULL;
6048 /* Use the original stream. */
6049 tmp = talloc_strdup(smb_fname_dst,
6050 smb_fname_orig_lcomp->stream_name);
6051 if (tmp == NULL) {
6052 status = NT_STATUS_NO_MEMORY;
6053 TALLOC_FREE(fname_dst_lcomp_base_mod);
6054 TALLOC_FREE(smb_fname_orig_lcomp);
6055 goto out;
6057 TALLOC_FREE(smb_fname_dst->stream_name);
6058 smb_fname_dst->stream_name = tmp;
6060 TALLOC_FREE(fname_dst_lcomp_base_mod);
6061 TALLOC_FREE(smb_fname_orig_lcomp);
6065 * If the src and dest names are identical - including case,
6066 * don't do the rename, just return success.
6069 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6070 strcsequal(fsp->fsp_name->stream_name,
6071 smb_fname_dst->stream_name)) {
6072 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6073 "- returning success\n",
6074 smb_fname_str_dbg(smb_fname_dst)));
6075 status = NT_STATUS_OK;
6076 goto out;
6079 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6080 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6082 /* Return the correct error code if both names aren't streams. */
6083 if (!old_is_stream && new_is_stream) {
6084 status = NT_STATUS_OBJECT_NAME_INVALID;
6085 goto out;
6088 if (old_is_stream && !new_is_stream) {
6089 status = NT_STATUS_INVALID_PARAMETER;
6090 goto out;
6093 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6095 if(!replace_if_exists && dst_exists) {
6096 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6097 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6098 smb_fname_str_dbg(smb_fname_dst)));
6099 status = NT_STATUS_OBJECT_NAME_COLLISION;
6100 goto out;
6103 if (dst_exists) {
6104 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6105 &smb_fname_dst->st);
6106 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6107 fileid);
6108 /* The file can be open when renaming a stream */
6109 if (dst_fsp && !new_is_stream) {
6110 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6111 status = NT_STATUS_ACCESS_DENIED;
6112 goto out;
6116 /* Ensure we have a valid stat struct for the source. */
6117 status = vfs_stat_fsp(fsp);
6118 if (!NT_STATUS_IS_OK(status)) {
6119 goto out;
6122 status = can_rename(conn, fsp, attrs);
6124 if (!NT_STATUS_IS_OK(status)) {
6125 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6126 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6127 smb_fname_str_dbg(smb_fname_dst)));
6128 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6129 status = NT_STATUS_ACCESS_DENIED;
6130 goto out;
6133 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6134 status = NT_STATUS_ACCESS_DENIED;
6137 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6140 * We have the file open ourselves, so not being able to get the
6141 * corresponding share mode lock is a fatal error.
6144 SMB_ASSERT(lck != NULL);
6146 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6147 uint32 create_options = fsp->fh->private_options;
6149 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6150 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6151 smb_fname_str_dbg(smb_fname_dst)));
6153 if (!lp_posix_pathnames() &&
6154 (lp_map_archive(SNUM(conn)) ||
6155 lp_store_dos_attributes(SNUM(conn)))) {
6156 /* We must set the archive bit on the newly
6157 renamed file. */
6158 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6159 uint32_t old_dosmode = dos_mode(conn,
6160 smb_fname_dst);
6161 file_set_dosmode(conn,
6162 smb_fname_dst,
6163 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6164 NULL,
6165 true);
6169 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6170 smb_fname_dst);
6172 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6175 * A rename acts as a new file create w.r.t. allowing an initial delete
6176 * on close, probably because in Windows there is a new handle to the
6177 * new file. If initial delete on close was requested but not
6178 * originally set, we need to set it here. This is probably not 100% correct,
6179 * but will work for the CIFSFS client which in non-posix mode
6180 * depends on these semantics. JRA.
6183 if (create_options & FILE_DELETE_ON_CLOSE) {
6184 status = can_set_delete_on_close(fsp, 0);
6186 if (NT_STATUS_IS_OK(status)) {
6187 /* Note that here we set the *inital* delete on close flag,
6188 * not the regular one. The magic gets handled in close. */
6189 fsp->initial_delete_on_close = True;
6192 TALLOC_FREE(lck);
6193 status = NT_STATUS_OK;
6194 goto out;
6197 TALLOC_FREE(lck);
6199 if (errno == ENOTDIR || errno == EISDIR) {
6200 status = NT_STATUS_OBJECT_NAME_COLLISION;
6201 } else {
6202 status = map_nt_error_from_unix(errno);
6205 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6206 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6207 smb_fname_str_dbg(smb_fname_dst)));
6209 out:
6210 TALLOC_FREE(smb_fname_dst);
6212 return status;
6215 /****************************************************************************
6216 The guts of the rename command, split out so it may be called by the NT SMB
6217 code.
6218 ****************************************************************************/
6220 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6221 connection_struct *conn,
6222 struct smb_request *req,
6223 struct smb_filename *smb_fname_src,
6224 struct smb_filename *smb_fname_dst,
6225 uint32 attrs,
6226 bool replace_if_exists,
6227 bool src_has_wild,
6228 bool dest_has_wild,
6229 uint32_t access_mask)
6231 char *fname_src_dir = NULL;
6232 char *fname_src_mask = NULL;
6233 int count=0;
6234 NTSTATUS status = NT_STATUS_OK;
6235 struct smb_Dir *dir_hnd = NULL;
6236 const char *dname = NULL;
6237 char *talloced = NULL;
6238 long offset = 0;
6239 int create_options = 0;
6240 bool posix_pathnames = lp_posix_pathnames();
6243 * Split the old name into directory and last component
6244 * strings. Note that unix_convert may have stripped off a
6245 * leading ./ from both name and newname if the rename is
6246 * at the root of the share. We need to make sure either both
6247 * name and newname contain a / character or neither of them do
6248 * as this is checked in resolve_wildcards().
6251 /* Split up the directory from the filename/mask. */
6252 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6253 &fname_src_dir, &fname_src_mask);
6254 if (!NT_STATUS_IS_OK(status)) {
6255 status = NT_STATUS_NO_MEMORY;
6256 goto out;
6260 * We should only check the mangled cache
6261 * here if unix_convert failed. This means
6262 * that the path in 'mask' doesn't exist
6263 * on the file system and so we need to look
6264 * for a possible mangle. This patch from
6265 * Tine Smukavec <valentin.smukavec@hermes.si>.
6268 if (!VALID_STAT(smb_fname_src->st) &&
6269 mangle_is_mangled(fname_src_mask, conn->params)) {
6270 char *new_mask = NULL;
6271 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6272 conn->params);
6273 if (new_mask) {
6274 TALLOC_FREE(fname_src_mask);
6275 fname_src_mask = new_mask;
6279 if (!src_has_wild) {
6280 files_struct *fsp;
6283 * Only one file needs to be renamed. Append the mask back
6284 * onto the directory.
6286 TALLOC_FREE(smb_fname_src->base_name);
6287 if (ISDOT(fname_src_dir)) {
6288 /* Ensure we use canonical names on open. */
6289 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6290 "%s",
6291 fname_src_mask);
6292 } else {
6293 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6294 "%s/%s",
6295 fname_src_dir,
6296 fname_src_mask);
6298 if (!smb_fname_src->base_name) {
6299 status = NT_STATUS_NO_MEMORY;
6300 goto out;
6303 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6304 "case_preserve = %d, short case preserve = %d, "
6305 "directory = %s, newname = %s, "
6306 "last_component_dest = %s\n",
6307 conn->case_sensitive, conn->case_preserve,
6308 conn->short_case_preserve,
6309 smb_fname_str_dbg(smb_fname_src),
6310 smb_fname_str_dbg(smb_fname_dst),
6311 smb_fname_dst->original_lcomp));
6313 /* The dest name still may have wildcards. */
6314 if (dest_has_wild) {
6315 char *fname_dst_mod = NULL;
6316 if (!resolve_wildcards(smb_fname_dst,
6317 smb_fname_src->base_name,
6318 smb_fname_dst->base_name,
6319 &fname_dst_mod)) {
6320 DEBUG(6, ("rename_internals: resolve_wildcards "
6321 "%s %s failed\n",
6322 smb_fname_src->base_name,
6323 smb_fname_dst->base_name));
6324 status = NT_STATUS_NO_MEMORY;
6325 goto out;
6327 TALLOC_FREE(smb_fname_dst->base_name);
6328 smb_fname_dst->base_name = fname_dst_mod;
6331 ZERO_STRUCT(smb_fname_src->st);
6332 if (posix_pathnames) {
6333 SMB_VFS_LSTAT(conn, smb_fname_src);
6334 } else {
6335 SMB_VFS_STAT(conn, smb_fname_src);
6338 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6339 create_options |= FILE_DIRECTORY_FILE;
6342 status = SMB_VFS_CREATE_FILE(
6343 conn, /* conn */
6344 req, /* req */
6345 0, /* root_dir_fid */
6346 smb_fname_src, /* fname */
6347 access_mask, /* access_mask */
6348 (FILE_SHARE_READ | /* share_access */
6349 FILE_SHARE_WRITE),
6350 FILE_OPEN, /* create_disposition*/
6351 create_options, /* create_options */
6352 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6353 0, /* oplock_request */
6354 0, /* allocation_size */
6355 0, /* private_flags */
6356 NULL, /* sd */
6357 NULL, /* ea_list */
6358 &fsp, /* result */
6359 NULL); /* pinfo */
6361 if (!NT_STATUS_IS_OK(status)) {
6362 DEBUG(3, ("Could not open rename source %s: %s\n",
6363 smb_fname_str_dbg(smb_fname_src),
6364 nt_errstr(status)));
6365 goto out;
6368 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6369 attrs, replace_if_exists);
6371 close_file(req, fsp, NORMAL_CLOSE);
6373 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6374 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6375 smb_fname_str_dbg(smb_fname_dst)));
6377 goto out;
6381 * Wildcards - process each file that matches.
6383 if (strequal(fname_src_mask, "????????.???")) {
6384 TALLOC_FREE(fname_src_mask);
6385 fname_src_mask = talloc_strdup(ctx, "*");
6386 if (!fname_src_mask) {
6387 status = NT_STATUS_NO_MEMORY;
6388 goto out;
6392 status = check_name(conn, fname_src_dir);
6393 if (!NT_STATUS_IS_OK(status)) {
6394 goto out;
6397 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6398 attrs);
6399 if (dir_hnd == NULL) {
6400 status = map_nt_error_from_unix(errno);
6401 goto out;
6404 status = NT_STATUS_NO_SUCH_FILE;
6406 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6407 * - gentest fix. JRA
6410 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6411 &talloced))) {
6412 files_struct *fsp = NULL;
6413 char *destname = NULL;
6414 bool sysdir_entry = False;
6416 /* Quick check for "." and ".." */
6417 if (ISDOT(dname) || ISDOTDOT(dname)) {
6418 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6419 sysdir_entry = True;
6420 } else {
6421 TALLOC_FREE(talloced);
6422 continue;
6426 if (!is_visible_file(conn, fname_src_dir, dname,
6427 &smb_fname_src->st, false)) {
6428 TALLOC_FREE(talloced);
6429 continue;
6432 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6433 TALLOC_FREE(talloced);
6434 continue;
6437 if (sysdir_entry) {
6438 status = NT_STATUS_OBJECT_NAME_INVALID;
6439 break;
6442 TALLOC_FREE(smb_fname_src->base_name);
6443 if (ISDOT(fname_src_dir)) {
6444 /* Ensure we use canonical names on open. */
6445 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6446 "%s",
6447 dname);
6448 } else {
6449 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6450 "%s/%s",
6451 fname_src_dir,
6452 dname);
6454 if (!smb_fname_src->base_name) {
6455 status = NT_STATUS_NO_MEMORY;
6456 goto out;
6459 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6460 smb_fname_dst->base_name,
6461 &destname)) {
6462 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6463 smb_fname_src->base_name, destname));
6464 TALLOC_FREE(talloced);
6465 continue;
6467 if (!destname) {
6468 status = NT_STATUS_NO_MEMORY;
6469 goto out;
6472 TALLOC_FREE(smb_fname_dst->base_name);
6473 smb_fname_dst->base_name = destname;
6475 ZERO_STRUCT(smb_fname_src->st);
6476 if (posix_pathnames) {
6477 SMB_VFS_LSTAT(conn, smb_fname_src);
6478 } else {
6479 SMB_VFS_STAT(conn, smb_fname_src);
6482 create_options = 0;
6484 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6485 create_options |= FILE_DIRECTORY_FILE;
6488 status = SMB_VFS_CREATE_FILE(
6489 conn, /* conn */
6490 req, /* req */
6491 0, /* root_dir_fid */
6492 smb_fname_src, /* fname */
6493 access_mask, /* access_mask */
6494 (FILE_SHARE_READ | /* share_access */
6495 FILE_SHARE_WRITE),
6496 FILE_OPEN, /* create_disposition*/
6497 create_options, /* create_options */
6498 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6499 0, /* oplock_request */
6500 0, /* allocation_size */
6501 0, /* private_flags */
6502 NULL, /* sd */
6503 NULL, /* ea_list */
6504 &fsp, /* result */
6505 NULL); /* pinfo */
6507 if (!NT_STATUS_IS_OK(status)) {
6508 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6509 "returned %s rename %s -> %s\n",
6510 nt_errstr(status),
6511 smb_fname_str_dbg(smb_fname_src),
6512 smb_fname_str_dbg(smb_fname_dst)));
6513 break;
6516 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6517 dname);
6518 if (!smb_fname_dst->original_lcomp) {
6519 status = NT_STATUS_NO_MEMORY;
6520 goto out;
6523 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6524 attrs, replace_if_exists);
6526 close_file(req, fsp, NORMAL_CLOSE);
6528 if (!NT_STATUS_IS_OK(status)) {
6529 DEBUG(3, ("rename_internals_fsp returned %s for "
6530 "rename %s -> %s\n", nt_errstr(status),
6531 smb_fname_str_dbg(smb_fname_src),
6532 smb_fname_str_dbg(smb_fname_dst)));
6533 break;
6536 count++;
6538 DEBUG(3,("rename_internals: doing rename on %s -> "
6539 "%s\n", smb_fname_str_dbg(smb_fname_src),
6540 smb_fname_str_dbg(smb_fname_src)));
6541 TALLOC_FREE(talloced);
6543 TALLOC_FREE(dir_hnd);
6545 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6546 status = map_nt_error_from_unix(errno);
6549 out:
6550 TALLOC_FREE(talloced);
6551 TALLOC_FREE(fname_src_dir);
6552 TALLOC_FREE(fname_src_mask);
6553 return status;
6556 /****************************************************************************
6557 Reply to a mv.
6558 ****************************************************************************/
6560 void reply_mv(struct smb_request *req)
6562 connection_struct *conn = req->conn;
6563 char *name = NULL;
6564 char *newname = NULL;
6565 const char *p;
6566 uint32 attrs;
6567 NTSTATUS status;
6568 bool src_has_wcard = False;
6569 bool dest_has_wcard = False;
6570 TALLOC_CTX *ctx = talloc_tos();
6571 struct smb_filename *smb_fname_src = NULL;
6572 struct smb_filename *smb_fname_dst = NULL;
6573 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6574 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6575 bool stream_rename = false;
6577 START_PROFILE(SMBmv);
6579 if (req->wct < 1) {
6580 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6581 goto out;
6584 attrs = SVAL(req->vwv+0, 0);
6586 p = (const char *)req->buf + 1;
6587 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6588 &status, &src_has_wcard);
6589 if (!NT_STATUS_IS_OK(status)) {
6590 reply_nterror(req, status);
6591 goto out;
6593 p++;
6594 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6595 &status, &dest_has_wcard);
6596 if (!NT_STATUS_IS_OK(status)) {
6597 reply_nterror(req, status);
6598 goto out;
6601 if (!lp_posix_pathnames()) {
6602 /* The newname must begin with a ':' if the
6603 name contains a ':'. */
6604 if (strchr_m(name, ':')) {
6605 if (newname[0] != ':') {
6606 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6607 goto out;
6609 stream_rename = true;
6613 status = filename_convert(ctx,
6614 conn,
6615 req->flags2 & FLAGS2_DFS_PATHNAMES,
6616 name,
6617 src_ucf_flags,
6618 &src_has_wcard,
6619 &smb_fname_src);
6621 if (!NT_STATUS_IS_OK(status)) {
6622 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6623 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6624 ERRSRV, ERRbadpath);
6625 goto out;
6627 reply_nterror(req, status);
6628 goto out;
6631 status = filename_convert(ctx,
6632 conn,
6633 req->flags2 & FLAGS2_DFS_PATHNAMES,
6634 newname,
6635 dst_ucf_flags,
6636 &dest_has_wcard,
6637 &smb_fname_dst);
6639 if (!NT_STATUS_IS_OK(status)) {
6640 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6641 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6642 ERRSRV, ERRbadpath);
6643 goto out;
6645 reply_nterror(req, status);
6646 goto out;
6649 if (stream_rename) {
6650 /* smb_fname_dst->base_name must be the same as
6651 smb_fname_src->base_name. */
6652 TALLOC_FREE(smb_fname_dst->base_name);
6653 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6654 smb_fname_src->base_name);
6655 if (!smb_fname_dst->base_name) {
6656 reply_nterror(req, NT_STATUS_NO_MEMORY);
6657 goto out;
6661 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6662 smb_fname_str_dbg(smb_fname_dst)));
6664 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6665 attrs, False, src_has_wcard, dest_has_wcard,
6666 DELETE_ACCESS);
6667 if (!NT_STATUS_IS_OK(status)) {
6668 if (open_was_deferred(req->sconn, req->mid)) {
6669 /* We have re-scheduled this call. */
6670 goto out;
6672 reply_nterror(req, status);
6673 goto out;
6676 reply_outbuf(req, 0, 0);
6677 out:
6678 TALLOC_FREE(smb_fname_src);
6679 TALLOC_FREE(smb_fname_dst);
6680 END_PROFILE(SMBmv);
6681 return;
6684 /*******************************************************************
6685 Copy a file as part of a reply_copy.
6686 ******************************************************************/
6689 * TODO: check error codes on all callers
6692 NTSTATUS copy_file(TALLOC_CTX *ctx,
6693 connection_struct *conn,
6694 struct smb_filename *smb_fname_src,
6695 struct smb_filename *smb_fname_dst,
6696 int ofun,
6697 int count,
6698 bool target_is_directory)
6700 struct smb_filename *smb_fname_dst_tmp = NULL;
6701 off_t ret=-1;
6702 files_struct *fsp1,*fsp2;
6703 uint32 dosattrs;
6704 uint32 new_create_disposition;
6705 NTSTATUS status;
6708 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6709 if (!NT_STATUS_IS_OK(status)) {
6710 return status;
6714 * If the target is a directory, extract the last component from the
6715 * src filename and append it to the dst filename
6717 if (target_is_directory) {
6718 const char *p;
6720 /* dest/target can't be a stream if it's a directory. */
6721 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6723 p = strrchr_m(smb_fname_src->base_name,'/');
6724 if (p) {
6725 p++;
6726 } else {
6727 p = smb_fname_src->base_name;
6729 smb_fname_dst_tmp->base_name =
6730 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6732 if (!smb_fname_dst_tmp->base_name) {
6733 status = NT_STATUS_NO_MEMORY;
6734 goto out;
6738 status = vfs_file_exist(conn, smb_fname_src);
6739 if (!NT_STATUS_IS_OK(status)) {
6740 goto out;
6743 if (!target_is_directory && count) {
6744 new_create_disposition = FILE_OPEN;
6745 } else {
6746 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6747 0, ofun,
6748 NULL, NULL,
6749 &new_create_disposition,
6750 NULL,
6751 NULL)) {
6752 status = NT_STATUS_INVALID_PARAMETER;
6753 goto out;
6757 /* Open the src file for reading. */
6758 status = SMB_VFS_CREATE_FILE(
6759 conn, /* conn */
6760 NULL, /* req */
6761 0, /* root_dir_fid */
6762 smb_fname_src, /* fname */
6763 FILE_GENERIC_READ, /* access_mask */
6764 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6765 FILE_OPEN, /* create_disposition*/
6766 0, /* create_options */
6767 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6768 INTERNAL_OPEN_ONLY, /* oplock_request */
6769 0, /* allocation_size */
6770 0, /* private_flags */
6771 NULL, /* sd */
6772 NULL, /* ea_list */
6773 &fsp1, /* result */
6774 NULL); /* psbuf */
6776 if (!NT_STATUS_IS_OK(status)) {
6777 goto out;
6780 dosattrs = dos_mode(conn, smb_fname_src);
6782 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6783 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6786 /* Open the dst file for writing. */
6787 status = SMB_VFS_CREATE_FILE(
6788 conn, /* conn */
6789 NULL, /* req */
6790 0, /* root_dir_fid */
6791 smb_fname_dst, /* fname */
6792 FILE_GENERIC_WRITE, /* access_mask */
6793 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6794 new_create_disposition, /* create_disposition*/
6795 0, /* create_options */
6796 dosattrs, /* file_attributes */
6797 INTERNAL_OPEN_ONLY, /* oplock_request */
6798 0, /* allocation_size */
6799 0, /* private_flags */
6800 NULL, /* sd */
6801 NULL, /* ea_list */
6802 &fsp2, /* result */
6803 NULL); /* psbuf */
6805 if (!NT_STATUS_IS_OK(status)) {
6806 close_file(NULL, fsp1, ERROR_CLOSE);
6807 goto out;
6810 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6811 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6812 if (ret == -1) {
6813 DEBUG(0, ("error - vfs lseek returned error %s\n",
6814 strerror(errno)));
6815 status = map_nt_error_from_unix(errno);
6816 close_file(NULL, fsp1, ERROR_CLOSE);
6817 close_file(NULL, fsp2, ERROR_CLOSE);
6818 goto out;
6822 /* Do the actual copy. */
6823 if (smb_fname_src->st.st_ex_size) {
6824 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6825 } else {
6826 ret = 0;
6829 close_file(NULL, fsp1, NORMAL_CLOSE);
6831 /* Ensure the modtime is set correctly on the destination file. */
6832 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6835 * As we are opening fsp1 read-only we only expect
6836 * an error on close on fsp2 if we are out of space.
6837 * Thus we don't look at the error return from the
6838 * close of fsp1.
6840 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6842 if (!NT_STATUS_IS_OK(status)) {
6843 goto out;
6846 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
6847 status = NT_STATUS_DISK_FULL;
6848 goto out;
6851 status = NT_STATUS_OK;
6853 out:
6854 TALLOC_FREE(smb_fname_dst_tmp);
6855 return status;
6858 /****************************************************************************
6859 Reply to a file copy.
6860 ****************************************************************************/
6862 void reply_copy(struct smb_request *req)
6864 connection_struct *conn = req->conn;
6865 struct smb_filename *smb_fname_src = NULL;
6866 struct smb_filename *smb_fname_dst = NULL;
6867 char *fname_src = NULL;
6868 char *fname_dst = NULL;
6869 char *fname_src_mask = NULL;
6870 char *fname_src_dir = NULL;
6871 const char *p;
6872 int count=0;
6873 int error = ERRnoaccess;
6874 int tid2;
6875 int ofun;
6876 int flags;
6877 bool target_is_directory=False;
6878 bool source_has_wild = False;
6879 bool dest_has_wild = False;
6880 NTSTATUS status;
6881 TALLOC_CTX *ctx = talloc_tos();
6883 START_PROFILE(SMBcopy);
6885 if (req->wct < 3) {
6886 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6887 goto out;
6890 tid2 = SVAL(req->vwv+0, 0);
6891 ofun = SVAL(req->vwv+1, 0);
6892 flags = SVAL(req->vwv+2, 0);
6894 p = (const char *)req->buf;
6895 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6896 &status, &source_has_wild);
6897 if (!NT_STATUS_IS_OK(status)) {
6898 reply_nterror(req, status);
6899 goto out;
6901 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6902 &status, &dest_has_wild);
6903 if (!NT_STATUS_IS_OK(status)) {
6904 reply_nterror(req, status);
6905 goto out;
6908 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6910 if (tid2 != conn->cnum) {
6911 /* can't currently handle inter share copies XXXX */
6912 DEBUG(3,("Rejecting inter-share copy\n"));
6913 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6914 goto out;
6917 status = filename_convert(ctx, conn,
6918 req->flags2 & FLAGS2_DFS_PATHNAMES,
6919 fname_src,
6920 UCF_COND_ALLOW_WCARD_LCOMP,
6921 &source_has_wild,
6922 &smb_fname_src);
6923 if (!NT_STATUS_IS_OK(status)) {
6924 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6925 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6926 ERRSRV, ERRbadpath);
6927 goto out;
6929 reply_nterror(req, status);
6930 goto out;
6933 status = filename_convert(ctx, conn,
6934 req->flags2 & FLAGS2_DFS_PATHNAMES,
6935 fname_dst,
6936 UCF_COND_ALLOW_WCARD_LCOMP,
6937 &dest_has_wild,
6938 &smb_fname_dst);
6939 if (!NT_STATUS_IS_OK(status)) {
6940 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6941 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6942 ERRSRV, ERRbadpath);
6943 goto out;
6945 reply_nterror(req, status);
6946 goto out;
6949 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6951 if ((flags&1) && target_is_directory) {
6952 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6953 goto out;
6956 if ((flags&2) && !target_is_directory) {
6957 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6958 goto out;
6961 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6962 /* wants a tree copy! XXXX */
6963 DEBUG(3,("Rejecting tree copy\n"));
6964 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6965 goto out;
6968 /* Split up the directory from the filename/mask. */
6969 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6970 &fname_src_dir, &fname_src_mask);
6971 if (!NT_STATUS_IS_OK(status)) {
6972 reply_nterror(req, NT_STATUS_NO_MEMORY);
6973 goto out;
6977 * We should only check the mangled cache
6978 * here if unix_convert failed. This means
6979 * that the path in 'mask' doesn't exist
6980 * on the file system and so we need to look
6981 * for a possible mangle. This patch from
6982 * Tine Smukavec <valentin.smukavec@hermes.si>.
6984 if (!VALID_STAT(smb_fname_src->st) &&
6985 mangle_is_mangled(fname_src_mask, conn->params)) {
6986 char *new_mask = NULL;
6987 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6988 &new_mask, conn->params);
6990 /* Use demangled name if one was successfully found. */
6991 if (new_mask) {
6992 TALLOC_FREE(fname_src_mask);
6993 fname_src_mask = new_mask;
6997 if (!source_has_wild) {
7000 * Only one file needs to be copied. Append the mask back onto
7001 * the directory.
7003 TALLOC_FREE(smb_fname_src->base_name);
7004 if (ISDOT(fname_src_dir)) {
7005 /* Ensure we use canonical names on open. */
7006 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7007 "%s",
7008 fname_src_mask);
7009 } else {
7010 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7011 "%s/%s",
7012 fname_src_dir,
7013 fname_src_mask);
7015 if (!smb_fname_src->base_name) {
7016 reply_nterror(req, NT_STATUS_NO_MEMORY);
7017 goto out;
7020 if (dest_has_wild) {
7021 char *fname_dst_mod = NULL;
7022 if (!resolve_wildcards(smb_fname_dst,
7023 smb_fname_src->base_name,
7024 smb_fname_dst->base_name,
7025 &fname_dst_mod)) {
7026 reply_nterror(req, NT_STATUS_NO_MEMORY);
7027 goto out;
7029 TALLOC_FREE(smb_fname_dst->base_name);
7030 smb_fname_dst->base_name = fname_dst_mod;
7033 status = check_name(conn, smb_fname_src->base_name);
7034 if (!NT_STATUS_IS_OK(status)) {
7035 reply_nterror(req, status);
7036 goto out;
7039 status = check_name(conn, smb_fname_dst->base_name);
7040 if (!NT_STATUS_IS_OK(status)) {
7041 reply_nterror(req, status);
7042 goto out;
7045 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7046 ofun, count, target_is_directory);
7048 if(!NT_STATUS_IS_OK(status)) {
7049 reply_nterror(req, status);
7050 goto out;
7051 } else {
7052 count++;
7054 } else {
7055 struct smb_Dir *dir_hnd = NULL;
7056 const char *dname = NULL;
7057 char *talloced = NULL;
7058 long offset = 0;
7061 * There is a wildcard that requires us to actually read the
7062 * src dir and copy each file matching the mask to the dst.
7063 * Right now streams won't be copied, but this could
7064 * presumably be added with a nested loop for reach dir entry.
7066 SMB_ASSERT(!smb_fname_src->stream_name);
7067 SMB_ASSERT(!smb_fname_dst->stream_name);
7069 smb_fname_src->stream_name = NULL;
7070 smb_fname_dst->stream_name = NULL;
7072 if (strequal(fname_src_mask,"????????.???")) {
7073 TALLOC_FREE(fname_src_mask);
7074 fname_src_mask = talloc_strdup(ctx, "*");
7075 if (!fname_src_mask) {
7076 reply_nterror(req, NT_STATUS_NO_MEMORY);
7077 goto out;
7081 status = check_name(conn, fname_src_dir);
7082 if (!NT_STATUS_IS_OK(status)) {
7083 reply_nterror(req, status);
7084 goto out;
7087 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7088 if (dir_hnd == NULL) {
7089 status = map_nt_error_from_unix(errno);
7090 reply_nterror(req, status);
7091 goto out;
7094 error = ERRbadfile;
7096 /* Iterate over the src dir copying each entry to the dst. */
7097 while ((dname = ReadDirName(dir_hnd, &offset,
7098 &smb_fname_src->st, &talloced))) {
7099 char *destname = NULL;
7101 if (ISDOT(dname) || ISDOTDOT(dname)) {
7102 TALLOC_FREE(talloced);
7103 continue;
7106 if (!is_visible_file(conn, fname_src_dir, dname,
7107 &smb_fname_src->st, false)) {
7108 TALLOC_FREE(talloced);
7109 continue;
7112 if(!mask_match(dname, fname_src_mask,
7113 conn->case_sensitive)) {
7114 TALLOC_FREE(talloced);
7115 continue;
7118 error = ERRnoaccess;
7120 /* Get the src smb_fname struct setup. */
7121 TALLOC_FREE(smb_fname_src->base_name);
7122 if (ISDOT(fname_src_dir)) {
7123 /* Ensure we use canonical names on open. */
7124 smb_fname_src->base_name =
7125 talloc_asprintf(smb_fname_src, "%s",
7126 dname);
7127 } else {
7128 smb_fname_src->base_name =
7129 talloc_asprintf(smb_fname_src, "%s/%s",
7130 fname_src_dir, dname);
7133 if (!smb_fname_src->base_name) {
7134 TALLOC_FREE(dir_hnd);
7135 TALLOC_FREE(talloced);
7136 reply_nterror(req, NT_STATUS_NO_MEMORY);
7137 goto out;
7140 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7141 smb_fname_dst->base_name,
7142 &destname)) {
7143 TALLOC_FREE(talloced);
7144 continue;
7146 if (!destname) {
7147 TALLOC_FREE(dir_hnd);
7148 TALLOC_FREE(talloced);
7149 reply_nterror(req, NT_STATUS_NO_MEMORY);
7150 goto out;
7153 TALLOC_FREE(smb_fname_dst->base_name);
7154 smb_fname_dst->base_name = destname;
7156 status = check_name(conn, smb_fname_src->base_name);
7157 if (!NT_STATUS_IS_OK(status)) {
7158 TALLOC_FREE(dir_hnd);
7159 TALLOC_FREE(talloced);
7160 reply_nterror(req, status);
7161 goto out;
7164 status = check_name(conn, smb_fname_dst->base_name);
7165 if (!NT_STATUS_IS_OK(status)) {
7166 TALLOC_FREE(dir_hnd);
7167 TALLOC_FREE(talloced);
7168 reply_nterror(req, status);
7169 goto out;
7172 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7173 smb_fname_src->base_name,
7174 smb_fname_dst->base_name));
7176 status = copy_file(ctx, conn, smb_fname_src,
7177 smb_fname_dst, ofun, count,
7178 target_is_directory);
7179 if (NT_STATUS_IS_OK(status)) {
7180 count++;
7183 TALLOC_FREE(talloced);
7185 TALLOC_FREE(dir_hnd);
7188 if (count == 0) {
7189 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7190 goto out;
7193 reply_outbuf(req, 1, 0);
7194 SSVAL(req->outbuf,smb_vwv0,count);
7195 out:
7196 TALLOC_FREE(smb_fname_src);
7197 TALLOC_FREE(smb_fname_dst);
7198 TALLOC_FREE(fname_src);
7199 TALLOC_FREE(fname_dst);
7200 TALLOC_FREE(fname_src_mask);
7201 TALLOC_FREE(fname_src_dir);
7203 END_PROFILE(SMBcopy);
7204 return;
7207 #undef DBGC_CLASS
7208 #define DBGC_CLASS DBGC_LOCKING
7210 /****************************************************************************
7211 Get a lock pid, dealing with large count requests.
7212 ****************************************************************************/
7214 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7215 bool large_file_format)
7217 if(!large_file_format)
7218 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7219 else
7220 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7223 /****************************************************************************
7224 Get a lock count, dealing with large count requests.
7225 ****************************************************************************/
7227 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7228 bool large_file_format)
7230 uint64_t count = 0;
7232 if(!large_file_format) {
7233 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7234 } else {
7236 #if defined(HAVE_LONGLONG)
7237 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7238 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7239 #else /* HAVE_LONGLONG */
7242 * NT4.x seems to be broken in that it sends large file (64 bit)
7243 * lockingX calls even if the CAP_LARGE_FILES was *not*
7244 * negotiated. For boxes without large unsigned ints truncate the
7245 * lock count by dropping the top 32 bits.
7248 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7249 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7250 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7251 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7252 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7255 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7256 #endif /* HAVE_LONGLONG */
7259 return count;
7262 #if !defined(HAVE_LONGLONG)
7263 /****************************************************************************
7264 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7265 ****************************************************************************/
7267 static uint32 map_lock_offset(uint32 high, uint32 low)
7269 unsigned int i;
7270 uint32 mask = 0;
7271 uint32 highcopy = high;
7274 * Try and find out how many significant bits there are in high.
7277 for(i = 0; highcopy; i++)
7278 highcopy >>= 1;
7281 * We use 31 bits not 32 here as POSIX
7282 * lock offsets may not be negative.
7285 mask = (~0) << (31 - i);
7287 if(low & mask)
7288 return 0; /* Fail. */
7290 high <<= (31 - i);
7292 return (high|low);
7294 #endif /* !defined(HAVE_LONGLONG) */
7296 /****************************************************************************
7297 Get a lock offset, dealing with large offset requests.
7298 ****************************************************************************/
7300 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7301 bool large_file_format, bool *err)
7303 uint64_t offset = 0;
7305 *err = False;
7307 if(!large_file_format) {
7308 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7309 } else {
7311 #if defined(HAVE_LONGLONG)
7312 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7313 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7314 #else /* HAVE_LONGLONG */
7317 * NT4.x seems to be broken in that it sends large file (64 bit)
7318 * lockingX calls even if the CAP_LARGE_FILES was *not*
7319 * negotiated. For boxes without large unsigned ints mangle the
7320 * lock offset by mapping the top 32 bits onto the lower 32.
7323 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7324 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7325 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7326 uint32 new_low = 0;
7328 if((new_low = map_lock_offset(high, low)) == 0) {
7329 *err = True;
7330 return (uint64_t)-1;
7333 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7334 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7335 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7336 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7339 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7340 #endif /* HAVE_LONGLONG */
7343 return offset;
7346 NTSTATUS smbd_do_locking(struct smb_request *req,
7347 files_struct *fsp,
7348 uint8_t type,
7349 int32_t timeout,
7350 uint16_t num_ulocks,
7351 struct smbd_lock_element *ulocks,
7352 uint16_t num_locks,
7353 struct smbd_lock_element *locks,
7354 bool *async)
7356 connection_struct *conn = req->conn;
7357 int i;
7358 NTSTATUS status = NT_STATUS_OK;
7360 *async = false;
7362 /* Data now points at the beginning of the list
7363 of smb_unlkrng structs */
7364 for(i = 0; i < (int)num_ulocks; i++) {
7365 struct smbd_lock_element *e = &ulocks[i];
7367 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7368 "pid %u, file %s\n",
7369 (double)e->offset,
7370 (double)e->count,
7371 (unsigned int)e->smblctx,
7372 fsp_str_dbg(fsp)));
7374 if (e->brltype != UNLOCK_LOCK) {
7375 /* this can only happen with SMB2 */
7376 return NT_STATUS_INVALID_PARAMETER;
7379 status = do_unlock(req->sconn->msg_ctx,
7380 fsp,
7381 e->smblctx,
7382 e->count,
7383 e->offset,
7384 WINDOWS_LOCK);
7386 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7387 nt_errstr(status)));
7389 if (!NT_STATUS_IS_OK(status)) {
7390 return status;
7394 /* Setup the timeout in seconds. */
7396 if (!lp_blocking_locks(SNUM(conn))) {
7397 timeout = 0;
7400 /* Data now points at the beginning of the list
7401 of smb_lkrng structs */
7403 for(i = 0; i < (int)num_locks; i++) {
7404 struct smbd_lock_element *e = &locks[i];
7406 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7407 "%llu, file %s timeout = %d\n",
7408 (double)e->offset,
7409 (double)e->count,
7410 (unsigned long long)e->smblctx,
7411 fsp_str_dbg(fsp),
7412 (int)timeout));
7414 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7415 struct blocking_lock_record *blr = NULL;
7417 if (num_locks > 1) {
7419 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7420 * if the lock vector contains one entry. When given mutliple cancel
7421 * requests in a single PDU we expect the server to return an
7422 * error. Windows servers seem to accept the request but only
7423 * cancel the first lock.
7424 * JRA - Do what Windows does (tm) :-).
7427 #if 0
7428 /* MS-CIFS (2.2.4.32.1) behavior. */
7429 return NT_STATUS_DOS(ERRDOS,
7430 ERRcancelviolation);
7431 #else
7432 /* Windows behavior. */
7433 if (i != 0) {
7434 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7435 "cancel request\n"));
7436 continue;
7438 #endif
7441 if (lp_blocking_locks(SNUM(conn))) {
7443 /* Schedule a message to ourselves to
7444 remove the blocking lock record and
7445 return the right error. */
7447 blr = blocking_lock_cancel_smb1(fsp,
7448 e->smblctx,
7449 e->offset,
7450 e->count,
7451 WINDOWS_LOCK,
7452 type,
7453 NT_STATUS_FILE_LOCK_CONFLICT);
7454 if (blr == NULL) {
7455 return NT_STATUS_DOS(
7456 ERRDOS,
7457 ERRcancelviolation);
7460 /* Remove a matching pending lock. */
7461 status = do_lock_cancel(fsp,
7462 e->smblctx,
7463 e->count,
7464 e->offset,
7465 WINDOWS_LOCK,
7466 blr);
7467 } else {
7468 bool blocking_lock = timeout ? true : false;
7469 bool defer_lock = false;
7470 struct byte_range_lock *br_lck;
7471 uint64_t block_smblctx;
7473 br_lck = do_lock(req->sconn->msg_ctx,
7474 fsp,
7475 e->smblctx,
7476 e->count,
7477 e->offset,
7478 e->brltype,
7479 WINDOWS_LOCK,
7480 blocking_lock,
7481 &status,
7482 &block_smblctx,
7483 NULL);
7485 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7486 /* Windows internal resolution for blocking locks seems
7487 to be about 200ms... Don't wait for less than that. JRA. */
7488 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7489 timeout = lp_lock_spin_time();
7491 defer_lock = true;
7494 /* If a lock sent with timeout of zero would fail, and
7495 * this lock has been requested multiple times,
7496 * according to brl_lock_failed() we convert this
7497 * request to a blocking lock with a timeout of between
7498 * 150 - 300 milliseconds.
7500 * If lp_lock_spin_time() has been set to 0, we skip
7501 * this blocking retry and fail immediately.
7503 * Replacement for do_lock_spin(). JRA. */
7505 if (!req->sconn->using_smb2 &&
7506 br_lck && lp_blocking_locks(SNUM(conn)) &&
7507 lp_lock_spin_time() && !blocking_lock &&
7508 NT_STATUS_EQUAL((status),
7509 NT_STATUS_FILE_LOCK_CONFLICT))
7511 defer_lock = true;
7512 timeout = lp_lock_spin_time();
7515 if (br_lck && defer_lock) {
7517 * A blocking lock was requested. Package up
7518 * this smb into a queued request and push it
7519 * onto the blocking lock queue.
7521 if(push_blocking_lock_request(br_lck,
7522 req,
7523 fsp,
7524 timeout,
7526 e->smblctx,
7527 e->brltype,
7528 WINDOWS_LOCK,
7529 e->offset,
7530 e->count,
7531 block_smblctx)) {
7532 TALLOC_FREE(br_lck);
7533 *async = true;
7534 return NT_STATUS_OK;
7538 TALLOC_FREE(br_lck);
7541 if (!NT_STATUS_IS_OK(status)) {
7542 break;
7546 /* If any of the above locks failed, then we must unlock
7547 all of the previous locks (X/Open spec). */
7549 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7551 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7552 i = -1; /* we want to skip the for loop */
7556 * Ensure we don't do a remove on the lock that just failed,
7557 * as under POSIX rules, if we have a lock already there, we
7558 * will delete it (and we shouldn't) .....
7560 for(i--; i >= 0; i--) {
7561 struct smbd_lock_element *e = &locks[i];
7563 do_unlock(req->sconn->msg_ctx,
7564 fsp,
7565 e->smblctx,
7566 e->count,
7567 e->offset,
7568 WINDOWS_LOCK);
7570 return status;
7573 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7574 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7576 return NT_STATUS_OK;
7579 /****************************************************************************
7580 Reply to a lockingX request.
7581 ****************************************************************************/
7583 void reply_lockingX(struct smb_request *req)
7585 connection_struct *conn = req->conn;
7586 files_struct *fsp;
7587 unsigned char locktype;
7588 unsigned char oplocklevel;
7589 uint16 num_ulocks;
7590 uint16 num_locks;
7591 int32 lock_timeout;
7592 int i;
7593 const uint8_t *data;
7594 bool large_file_format;
7595 bool err;
7596 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7597 struct smbd_lock_element *ulocks;
7598 struct smbd_lock_element *locks;
7599 bool async = false;
7601 START_PROFILE(SMBlockingX);
7603 if (req->wct < 8) {
7604 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7605 END_PROFILE(SMBlockingX);
7606 return;
7609 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7610 locktype = CVAL(req->vwv+3, 0);
7611 oplocklevel = CVAL(req->vwv+3, 1);
7612 num_ulocks = SVAL(req->vwv+6, 0);
7613 num_locks = SVAL(req->vwv+7, 0);
7614 lock_timeout = IVAL(req->vwv+4, 0);
7615 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7617 if (!check_fsp(conn, req, fsp)) {
7618 END_PROFILE(SMBlockingX);
7619 return;
7622 data = req->buf;
7624 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7625 /* we don't support these - and CANCEL_LOCK makes w2k
7626 and XP reboot so I don't really want to be
7627 compatible! (tridge) */
7628 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7629 END_PROFILE(SMBlockingX);
7630 return;
7633 /* Check if this is an oplock break on a file
7634 we have granted an oplock on.
7636 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7637 /* Client can insist on breaking to none. */
7638 bool break_to_none = (oplocklevel == 0);
7639 bool result;
7641 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7642 "for fnum = %d\n", (unsigned int)oplocklevel,
7643 fsp->fnum ));
7646 * Make sure we have granted an exclusive or batch oplock on
7647 * this file.
7650 if (fsp->oplock_type == 0) {
7652 /* The Samba4 nbench simulator doesn't understand
7653 the difference between break to level2 and break
7654 to none from level2 - it sends oplock break
7655 replies in both cases. Don't keep logging an error
7656 message here - just ignore it. JRA. */
7658 DEBUG(5,("reply_lockingX: Error : oplock break from "
7659 "client for fnum = %d (oplock=%d) and no "
7660 "oplock granted on this file (%s).\n",
7661 fsp->fnum, fsp->oplock_type,
7662 fsp_str_dbg(fsp)));
7664 /* if this is a pure oplock break request then don't
7665 * send a reply */
7666 if (num_locks == 0 && num_ulocks == 0) {
7667 END_PROFILE(SMBlockingX);
7668 return;
7669 } else {
7670 END_PROFILE(SMBlockingX);
7671 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7672 return;
7676 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7677 (break_to_none)) {
7678 result = remove_oplock(fsp);
7679 } else {
7680 result = downgrade_oplock(fsp);
7683 if (!result) {
7684 DEBUG(0, ("reply_lockingX: error in removing "
7685 "oplock on file %s\n", fsp_str_dbg(fsp)));
7686 /* Hmmm. Is this panic justified? */
7687 smb_panic("internal tdb error");
7690 reply_to_oplock_break_requests(fsp);
7692 /* if this is a pure oplock break request then don't send a
7693 * reply */
7694 if (num_locks == 0 && num_ulocks == 0) {
7695 /* Sanity check - ensure a pure oplock break is not a
7696 chained request. */
7697 if(CVAL(req->vwv+0, 0) != 0xff)
7698 DEBUG(0,("reply_lockingX: Error : pure oplock "
7699 "break is a chained %d request !\n",
7700 (unsigned int)CVAL(req->vwv+0, 0)));
7701 END_PROFILE(SMBlockingX);
7702 return;
7706 if (req->buflen <
7707 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7708 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7709 END_PROFILE(SMBlockingX);
7710 return;
7713 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7714 if (ulocks == NULL) {
7715 reply_nterror(req, NT_STATUS_NO_MEMORY);
7716 END_PROFILE(SMBlockingX);
7717 return;
7720 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7721 if (locks == NULL) {
7722 reply_nterror(req, NT_STATUS_NO_MEMORY);
7723 END_PROFILE(SMBlockingX);
7724 return;
7727 /* Data now points at the beginning of the list
7728 of smb_unlkrng structs */
7729 for(i = 0; i < (int)num_ulocks; i++) {
7730 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7731 ulocks[i].count = get_lock_count(data, i, large_file_format);
7732 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7733 ulocks[i].brltype = UNLOCK_LOCK;
7736 * There is no error code marked "stupid client bug".... :-).
7738 if(err) {
7739 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7740 END_PROFILE(SMBlockingX);
7741 return;
7745 /* Now do any requested locks */
7746 data += ((large_file_format ? 20 : 10)*num_ulocks);
7748 /* Data now points at the beginning of the list
7749 of smb_lkrng structs */
7751 for(i = 0; i < (int)num_locks; i++) {
7752 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7753 locks[i].count = get_lock_count(data, i, large_file_format);
7754 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7756 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7757 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7758 locks[i].brltype = PENDING_READ_LOCK;
7759 } else {
7760 locks[i].brltype = READ_LOCK;
7762 } else {
7763 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7764 locks[i].brltype = PENDING_WRITE_LOCK;
7765 } else {
7766 locks[i].brltype = WRITE_LOCK;
7771 * There is no error code marked "stupid client bug".... :-).
7773 if(err) {
7774 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7775 END_PROFILE(SMBlockingX);
7776 return;
7780 status = smbd_do_locking(req, fsp,
7781 locktype, lock_timeout,
7782 num_ulocks, ulocks,
7783 num_locks, locks,
7784 &async);
7785 if (!NT_STATUS_IS_OK(status)) {
7786 END_PROFILE(SMBlockingX);
7787 reply_nterror(req, status);
7788 return;
7790 if (async) {
7791 END_PROFILE(SMBlockingX);
7792 return;
7795 reply_outbuf(req, 2, 0);
7796 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
7797 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
7799 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7800 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7802 END_PROFILE(SMBlockingX);
7805 #undef DBGC_CLASS
7806 #define DBGC_CLASS DBGC_ALL
7808 /****************************************************************************
7809 Reply to a SMBreadbmpx (read block multiplex) request.
7810 Always reply with an error, if someone has a platform really needs this,
7811 please contact vl@samba.org
7812 ****************************************************************************/
7814 void reply_readbmpx(struct smb_request *req)
7816 START_PROFILE(SMBreadBmpx);
7817 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7818 END_PROFILE(SMBreadBmpx);
7819 return;
7822 /****************************************************************************
7823 Reply to a SMBreadbs (read block multiplex secondary) request.
7824 Always reply with an error, if someone has a platform really needs this,
7825 please contact vl@samba.org
7826 ****************************************************************************/
7828 void reply_readbs(struct smb_request *req)
7830 START_PROFILE(SMBreadBs);
7831 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7832 END_PROFILE(SMBreadBs);
7833 return;
7836 /****************************************************************************
7837 Reply to a SMBsetattrE.
7838 ****************************************************************************/
7840 void reply_setattrE(struct smb_request *req)
7842 connection_struct *conn = req->conn;
7843 struct smb_file_time ft;
7844 files_struct *fsp;
7845 NTSTATUS status;
7847 START_PROFILE(SMBsetattrE);
7848 ZERO_STRUCT(ft);
7850 if (req->wct < 7) {
7851 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7852 goto out;
7855 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7857 if(!fsp || (fsp->conn != conn)) {
7858 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7859 goto out;
7863 * Convert the DOS times into unix times.
7866 ft.atime = convert_time_t_to_timespec(
7867 srv_make_unix_date2(req->vwv+3));
7868 ft.mtime = convert_time_t_to_timespec(
7869 srv_make_unix_date2(req->vwv+5));
7870 ft.create_time = convert_time_t_to_timespec(
7871 srv_make_unix_date2(req->vwv+1));
7873 reply_outbuf(req, 0, 0);
7876 * Patch from Ray Frush <frush@engr.colostate.edu>
7877 * Sometimes times are sent as zero - ignore them.
7880 /* Ensure we have a valid stat struct for the source. */
7881 status = vfs_stat_fsp(fsp);
7882 if (!NT_STATUS_IS_OK(status)) {
7883 reply_nterror(req, status);
7884 goto out;
7887 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
7888 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7889 goto out;
7892 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7893 if (!NT_STATUS_IS_OK(status)) {
7894 reply_nterror(req, status);
7895 goto out;
7898 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7899 " createtime=%u\n",
7900 fsp->fnum,
7901 (unsigned int)ft.atime.tv_sec,
7902 (unsigned int)ft.mtime.tv_sec,
7903 (unsigned int)ft.create_time.tv_sec
7905 out:
7906 END_PROFILE(SMBsetattrE);
7907 return;
7911 /* Back from the dead for OS/2..... JRA. */
7913 /****************************************************************************
7914 Reply to a SMBwritebmpx (write block multiplex primary) request.
7915 Always reply with an error, if someone has a platform really needs this,
7916 please contact vl@samba.org
7917 ****************************************************************************/
7919 void reply_writebmpx(struct smb_request *req)
7921 START_PROFILE(SMBwriteBmpx);
7922 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7923 END_PROFILE(SMBwriteBmpx);
7924 return;
7927 /****************************************************************************
7928 Reply to a SMBwritebs (write block multiplex secondary) request.
7929 Always reply with an error, if someone has a platform really needs this,
7930 please contact vl@samba.org
7931 ****************************************************************************/
7933 void reply_writebs(struct smb_request *req)
7935 START_PROFILE(SMBwriteBs);
7936 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7937 END_PROFILE(SMBwriteBs);
7938 return;
7941 /****************************************************************************
7942 Reply to a SMBgetattrE.
7943 ****************************************************************************/
7945 void reply_getattrE(struct smb_request *req)
7947 connection_struct *conn = req->conn;
7948 int mode;
7949 files_struct *fsp;
7950 struct timespec create_ts;
7952 START_PROFILE(SMBgetattrE);
7954 if (req->wct < 1) {
7955 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7956 END_PROFILE(SMBgetattrE);
7957 return;
7960 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7962 if(!fsp || (fsp->conn != conn)) {
7963 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7964 END_PROFILE(SMBgetattrE);
7965 return;
7968 /* Do an fstat on this file */
7969 if(fsp_stat(fsp)) {
7970 reply_nterror(req, map_nt_error_from_unix(errno));
7971 END_PROFILE(SMBgetattrE);
7972 return;
7975 mode = dos_mode(conn, fsp->fsp_name);
7978 * Convert the times into dos times. Set create
7979 * date to be last modify date as UNIX doesn't save
7980 * this.
7983 reply_outbuf(req, 11, 0);
7985 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7986 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7987 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7988 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7989 /* Should we check pending modtime here ? JRA */
7990 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7991 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7993 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
7994 SIVAL(req->outbuf, smb_vwv6, 0);
7995 SIVAL(req->outbuf, smb_vwv8, 0);
7996 } else {
7997 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7998 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7999 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8001 SSVAL(req->outbuf,smb_vwv10, mode);
8003 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
8005 END_PROFILE(SMBgetattrE);
8006 return;