Talloc doc: Fix a cut&paste error
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blobdc4310639b8a04049bbf2ac92afdf50ad2784420
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));
2090 /* in user level security we are supposed to close any files
2091 open by this user */
2092 if (vuser != NULL) {
2093 file_close_user(sconn, req->vuid);
2096 invalidate_vuid(sconn, req->vuid);
2098 reply_outbuf(req, 2, 0);
2099 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2100 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2102 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2104 END_PROFILE(SMBulogoffX);
2105 req->vuid = UID_FIELD_INVALID;
2108 /****************************************************************************
2109 Reply to a mknew or a create.
2110 ****************************************************************************/
2112 void reply_mknew(struct smb_request *req)
2114 connection_struct *conn = req->conn;
2115 struct smb_filename *smb_fname = NULL;
2116 char *fname = NULL;
2117 uint32 fattr = 0;
2118 struct smb_file_time ft;
2119 files_struct *fsp;
2120 int oplock_request = 0;
2121 NTSTATUS status;
2122 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2123 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2124 uint32 create_disposition;
2125 uint32 create_options = 0;
2126 TALLOC_CTX *ctx = talloc_tos();
2128 START_PROFILE(SMBcreate);
2129 ZERO_STRUCT(ft);
2131 if (req->wct < 3) {
2132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2133 goto out;
2136 fattr = SVAL(req->vwv+0, 0);
2137 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2139 /* mtime. */
2140 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2142 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2143 STR_TERMINATE, &status);
2144 if (!NT_STATUS_IS_OK(status)) {
2145 reply_nterror(req, status);
2146 goto out;
2149 status = filename_convert(ctx,
2150 conn,
2151 req->flags2 & FLAGS2_DFS_PATHNAMES,
2152 fname,
2154 NULL,
2155 &smb_fname);
2156 if (!NT_STATUS_IS_OK(status)) {
2157 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2158 reply_botherror(req,
2159 NT_STATUS_PATH_NOT_COVERED,
2160 ERRSRV, ERRbadpath);
2161 goto out;
2163 reply_nterror(req, status);
2164 goto out;
2167 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2168 DEBUG(0,("Attempt to create file (%s) with volid set - "
2169 "please report this\n",
2170 smb_fname_str_dbg(smb_fname)));
2173 if(req->cmd == SMBmknew) {
2174 /* We should fail if file exists. */
2175 create_disposition = FILE_CREATE;
2176 } else {
2177 /* Create if file doesn't exist, truncate if it does. */
2178 create_disposition = FILE_OVERWRITE_IF;
2181 status = SMB_VFS_CREATE_FILE(
2182 conn, /* conn */
2183 req, /* req */
2184 0, /* root_dir_fid */
2185 smb_fname, /* fname */
2186 access_mask, /* access_mask */
2187 share_mode, /* share_access */
2188 create_disposition, /* create_disposition*/
2189 create_options, /* create_options */
2190 fattr, /* file_attributes */
2191 oplock_request, /* oplock_request */
2192 0, /* allocation_size */
2193 0, /* private_flags */
2194 NULL, /* sd */
2195 NULL, /* ea_list */
2196 &fsp, /* result */
2197 NULL); /* pinfo */
2199 if (!NT_STATUS_IS_OK(status)) {
2200 if (open_was_deferred(req->sconn, req->mid)) {
2201 /* We have re-scheduled this call. */
2202 goto out;
2204 reply_openerror(req, status);
2205 goto out;
2208 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2209 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2210 if (!NT_STATUS_IS_OK(status)) {
2211 END_PROFILE(SMBcreate);
2212 goto out;
2215 reply_outbuf(req, 1, 0);
2216 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2218 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2219 SCVAL(req->outbuf,smb_flg,
2220 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2223 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2224 SCVAL(req->outbuf,smb_flg,
2225 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2228 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2229 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2230 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2231 (unsigned int)fattr));
2233 out:
2234 TALLOC_FREE(smb_fname);
2235 END_PROFILE(SMBcreate);
2236 return;
2239 /****************************************************************************
2240 Reply to a create temporary file.
2241 ****************************************************************************/
2243 void reply_ctemp(struct smb_request *req)
2245 connection_struct *conn = req->conn;
2246 struct smb_filename *smb_fname = NULL;
2247 char *fname = NULL;
2248 uint32 fattr;
2249 files_struct *fsp;
2250 int oplock_request;
2251 int tmpfd;
2252 char *s;
2253 NTSTATUS status;
2254 TALLOC_CTX *ctx = talloc_tos();
2256 START_PROFILE(SMBctemp);
2258 if (req->wct < 3) {
2259 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2260 goto out;
2263 fattr = SVAL(req->vwv+0, 0);
2264 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2266 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2267 STR_TERMINATE, &status);
2268 if (!NT_STATUS_IS_OK(status)) {
2269 reply_nterror(req, status);
2270 goto out;
2272 if (*fname) {
2273 fname = talloc_asprintf(ctx,
2274 "%s/TMXXXXXX",
2275 fname);
2276 } else {
2277 fname = talloc_strdup(ctx, "TMXXXXXX");
2280 if (!fname) {
2281 reply_nterror(req, NT_STATUS_NO_MEMORY);
2282 goto out;
2285 status = filename_convert(ctx, conn,
2286 req->flags2 & FLAGS2_DFS_PATHNAMES,
2287 fname,
2289 NULL,
2290 &smb_fname);
2291 if (!NT_STATUS_IS_OK(status)) {
2292 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2293 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2294 ERRSRV, ERRbadpath);
2295 goto out;
2297 reply_nterror(req, status);
2298 goto out;
2301 tmpfd = mkstemp(smb_fname->base_name);
2302 if (tmpfd == -1) {
2303 reply_nterror(req, map_nt_error_from_unix(errno));
2304 goto out;
2307 SMB_VFS_STAT(conn, smb_fname);
2309 /* We should fail if file does not exist. */
2310 status = SMB_VFS_CREATE_FILE(
2311 conn, /* conn */
2312 req, /* req */
2313 0, /* root_dir_fid */
2314 smb_fname, /* fname */
2315 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2316 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2317 FILE_OPEN, /* create_disposition*/
2318 0, /* create_options */
2319 fattr, /* file_attributes */
2320 oplock_request, /* oplock_request */
2321 0, /* allocation_size */
2322 0, /* private_flags */
2323 NULL, /* sd */
2324 NULL, /* ea_list */
2325 &fsp, /* result */
2326 NULL); /* pinfo */
2328 /* close fd from mkstemp() */
2329 close(tmpfd);
2331 if (!NT_STATUS_IS_OK(status)) {
2332 if (open_was_deferred(req->sconn, req->mid)) {
2333 /* We have re-scheduled this call. */
2334 goto out;
2336 reply_openerror(req, status);
2337 goto out;
2340 reply_outbuf(req, 1, 0);
2341 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2343 /* the returned filename is relative to the directory */
2344 s = strrchr_m(fsp->fsp_name->base_name, '/');
2345 if (!s) {
2346 s = fsp->fsp_name->base_name;
2347 } else {
2348 s++;
2351 #if 0
2352 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2353 thing in the byte section. JRA */
2354 SSVALS(p, 0, -1); /* what is this? not in spec */
2355 #endif
2356 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2357 == -1) {
2358 reply_nterror(req, NT_STATUS_NO_MEMORY);
2359 goto out;
2362 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2363 SCVAL(req->outbuf, smb_flg,
2364 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2367 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2368 SCVAL(req->outbuf, smb_flg,
2369 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2372 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2373 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2374 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2375 out:
2376 TALLOC_FREE(smb_fname);
2377 END_PROFILE(SMBctemp);
2378 return;
2381 /*******************************************************************
2382 Check if a user is allowed to rename a file.
2383 ********************************************************************/
2385 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2386 uint16 dirtype)
2388 if (!CAN_WRITE(conn)) {
2389 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2392 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2393 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2394 /* Only bother to read the DOS attribute if we might deny the
2395 rename on the grounds of attribute missmatch. */
2396 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2397 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2398 return NT_STATUS_NO_SUCH_FILE;
2402 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2403 if (fsp->posix_open) {
2404 return NT_STATUS_OK;
2407 /* If no pathnames are open below this
2408 directory, allow the rename. */
2410 if (file_find_subpath(fsp)) {
2411 return NT_STATUS_ACCESS_DENIED;
2413 return NT_STATUS_OK;
2416 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2417 return NT_STATUS_OK;
2420 return NT_STATUS_ACCESS_DENIED;
2423 /*******************************************************************
2424 * unlink a file with all relevant access checks
2425 *******************************************************************/
2427 static NTSTATUS do_unlink(connection_struct *conn,
2428 struct smb_request *req,
2429 struct smb_filename *smb_fname,
2430 uint32 dirtype)
2432 uint32 fattr;
2433 files_struct *fsp;
2434 uint32 dirtype_orig = dirtype;
2435 NTSTATUS status;
2436 int ret;
2437 bool posix_paths = lp_posix_pathnames();
2439 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2440 smb_fname_str_dbg(smb_fname),
2441 dirtype));
2443 if (!CAN_WRITE(conn)) {
2444 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2447 if (posix_paths) {
2448 ret = SMB_VFS_LSTAT(conn, smb_fname);
2449 } else {
2450 ret = SMB_VFS_STAT(conn, smb_fname);
2452 if (ret != 0) {
2453 return map_nt_error_from_unix(errno);
2456 fattr = dos_mode(conn, smb_fname);
2458 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2459 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2462 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2463 if (!dirtype) {
2464 return NT_STATUS_NO_SUCH_FILE;
2467 if (!dir_check_ftype(conn, fattr, dirtype)) {
2468 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2469 return NT_STATUS_FILE_IS_A_DIRECTORY;
2471 return NT_STATUS_NO_SUCH_FILE;
2474 if (dirtype_orig & 0x8000) {
2475 /* These will never be set for POSIX. */
2476 return NT_STATUS_NO_SUCH_FILE;
2479 #if 0
2480 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2481 return NT_STATUS_FILE_IS_A_DIRECTORY;
2484 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2485 return NT_STATUS_NO_SUCH_FILE;
2488 if (dirtype & 0xFF00) {
2489 /* These will never be set for POSIX. */
2490 return NT_STATUS_NO_SUCH_FILE;
2493 dirtype &= 0xFF;
2494 if (!dirtype) {
2495 return NT_STATUS_NO_SUCH_FILE;
2498 /* Can't delete a directory. */
2499 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2500 return NT_STATUS_FILE_IS_A_DIRECTORY;
2502 #endif
2504 #if 0 /* JRATEST */
2505 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2506 return NT_STATUS_OBJECT_NAME_INVALID;
2507 #endif /* JRATEST */
2509 /* On open checks the open itself will check the share mode, so
2510 don't do it here as we'll get it wrong. */
2512 status = SMB_VFS_CREATE_FILE
2513 (conn, /* conn */
2514 req, /* req */
2515 0, /* root_dir_fid */
2516 smb_fname, /* fname */
2517 DELETE_ACCESS, /* access_mask */
2518 FILE_SHARE_NONE, /* share_access */
2519 FILE_OPEN, /* create_disposition*/
2520 FILE_NON_DIRECTORY_FILE, /* create_options */
2521 /* file_attributes */
2522 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2523 FILE_ATTRIBUTE_NORMAL,
2524 0, /* oplock_request */
2525 0, /* allocation_size */
2526 0, /* private_flags */
2527 NULL, /* sd */
2528 NULL, /* ea_list */
2529 &fsp, /* result */
2530 NULL); /* pinfo */
2532 if (!NT_STATUS_IS_OK(status)) {
2533 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2534 nt_errstr(status)));
2535 return status;
2538 status = can_set_delete_on_close(fsp, fattr);
2539 if (!NT_STATUS_IS_OK(status)) {
2540 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2541 "(%s)\n",
2542 smb_fname_str_dbg(smb_fname),
2543 nt_errstr(status)));
2544 close_file(req, fsp, NORMAL_CLOSE);
2545 return status;
2548 /* The set is across all open files on this dev/inode pair. */
2549 if (!set_delete_on_close(fsp, True,
2550 conn->session_info->security_token,
2551 conn->session_info->unix_token)) {
2552 close_file(req, fsp, NORMAL_CLOSE);
2553 return NT_STATUS_ACCESS_DENIED;
2556 return close_file(req, fsp, NORMAL_CLOSE);
2559 /****************************************************************************
2560 The guts of the unlink command, split out so it may be called by the NT SMB
2561 code.
2562 ****************************************************************************/
2564 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2565 uint32 dirtype, struct smb_filename *smb_fname,
2566 bool has_wild)
2568 char *fname_dir = NULL;
2569 char *fname_mask = NULL;
2570 int count=0;
2571 NTSTATUS status = NT_STATUS_OK;
2572 TALLOC_CTX *ctx = talloc_tos();
2574 /* Split up the directory from the filename/mask. */
2575 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2576 &fname_dir, &fname_mask);
2577 if (!NT_STATUS_IS_OK(status)) {
2578 goto out;
2582 * We should only check the mangled cache
2583 * here if unix_convert failed. This means
2584 * that the path in 'mask' doesn't exist
2585 * on the file system and so we need to look
2586 * for a possible mangle. This patch from
2587 * Tine Smukavec <valentin.smukavec@hermes.si>.
2590 if (!VALID_STAT(smb_fname->st) &&
2591 mangle_is_mangled(fname_mask, conn->params)) {
2592 char *new_mask = NULL;
2593 mangle_lookup_name_from_8_3(ctx, fname_mask,
2594 &new_mask, conn->params);
2595 if (new_mask) {
2596 TALLOC_FREE(fname_mask);
2597 fname_mask = new_mask;
2601 if (!has_wild) {
2604 * Only one file needs to be unlinked. Append the mask back
2605 * onto the directory.
2607 TALLOC_FREE(smb_fname->base_name);
2608 if (ISDOT(fname_dir)) {
2609 /* Ensure we use canonical names on open. */
2610 smb_fname->base_name = talloc_asprintf(smb_fname,
2611 "%s",
2612 fname_mask);
2613 } else {
2614 smb_fname->base_name = talloc_asprintf(smb_fname,
2615 "%s/%s",
2616 fname_dir,
2617 fname_mask);
2619 if (!smb_fname->base_name) {
2620 status = NT_STATUS_NO_MEMORY;
2621 goto out;
2623 if (dirtype == 0) {
2624 dirtype = FILE_ATTRIBUTE_NORMAL;
2627 status = check_name(conn, smb_fname->base_name);
2628 if (!NT_STATUS_IS_OK(status)) {
2629 goto out;
2632 status = do_unlink(conn, req, smb_fname, dirtype);
2633 if (!NT_STATUS_IS_OK(status)) {
2634 goto out;
2637 count++;
2638 } else {
2639 struct smb_Dir *dir_hnd = NULL;
2640 long offset = 0;
2641 const char *dname = NULL;
2642 char *talloced = NULL;
2644 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2645 status = NT_STATUS_OBJECT_NAME_INVALID;
2646 goto out;
2649 if (strequal(fname_mask,"????????.???")) {
2650 TALLOC_FREE(fname_mask);
2651 fname_mask = talloc_strdup(ctx, "*");
2652 if (!fname_mask) {
2653 status = NT_STATUS_NO_MEMORY;
2654 goto out;
2658 status = check_name(conn, fname_dir);
2659 if (!NT_STATUS_IS_OK(status)) {
2660 goto out;
2663 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2664 dirtype);
2665 if (dir_hnd == NULL) {
2666 status = map_nt_error_from_unix(errno);
2667 goto out;
2670 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2671 the pattern matches against the long name, otherwise the short name
2672 We don't implement this yet XXXX
2675 status = NT_STATUS_NO_SUCH_FILE;
2677 while ((dname = ReadDirName(dir_hnd, &offset,
2678 &smb_fname->st, &talloced))) {
2679 TALLOC_CTX *frame = talloc_stackframe();
2681 if (!is_visible_file(conn, fname_dir, dname,
2682 &smb_fname->st, true)) {
2683 TALLOC_FREE(frame);
2684 TALLOC_FREE(talloced);
2685 continue;
2688 /* Quick check for "." and ".." */
2689 if (ISDOT(dname) || ISDOTDOT(dname)) {
2690 TALLOC_FREE(frame);
2691 TALLOC_FREE(talloced);
2692 continue;
2695 if(!mask_match(dname, fname_mask,
2696 conn->case_sensitive)) {
2697 TALLOC_FREE(frame);
2698 TALLOC_FREE(talloced);
2699 continue;
2702 TALLOC_FREE(smb_fname->base_name);
2703 if (ISDOT(fname_dir)) {
2704 /* Ensure we use canonical names on open. */
2705 smb_fname->base_name =
2706 talloc_asprintf(smb_fname, "%s",
2707 dname);
2708 } else {
2709 smb_fname->base_name =
2710 talloc_asprintf(smb_fname, "%s/%s",
2711 fname_dir, dname);
2714 if (!smb_fname->base_name) {
2715 TALLOC_FREE(dir_hnd);
2716 status = NT_STATUS_NO_MEMORY;
2717 TALLOC_FREE(frame);
2718 TALLOC_FREE(talloced);
2719 goto out;
2722 status = check_name(conn, smb_fname->base_name);
2723 if (!NT_STATUS_IS_OK(status)) {
2724 TALLOC_FREE(dir_hnd);
2725 TALLOC_FREE(frame);
2726 TALLOC_FREE(talloced);
2727 goto out;
2730 status = do_unlink(conn, req, smb_fname, dirtype);
2731 if (!NT_STATUS_IS_OK(status)) {
2732 TALLOC_FREE(frame);
2733 TALLOC_FREE(talloced);
2734 continue;
2737 count++;
2738 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2739 smb_fname->base_name));
2741 TALLOC_FREE(frame);
2742 TALLOC_FREE(talloced);
2744 TALLOC_FREE(dir_hnd);
2747 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2748 status = map_nt_error_from_unix(errno);
2751 out:
2752 TALLOC_FREE(fname_dir);
2753 TALLOC_FREE(fname_mask);
2754 return status;
2757 /****************************************************************************
2758 Reply to a unlink
2759 ****************************************************************************/
2761 void reply_unlink(struct smb_request *req)
2763 connection_struct *conn = req->conn;
2764 char *name = NULL;
2765 struct smb_filename *smb_fname = NULL;
2766 uint32 dirtype;
2767 NTSTATUS status;
2768 bool path_contains_wcard = False;
2769 TALLOC_CTX *ctx = talloc_tos();
2771 START_PROFILE(SMBunlink);
2773 if (req->wct < 1) {
2774 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2775 goto out;
2778 dirtype = SVAL(req->vwv+0, 0);
2780 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2781 STR_TERMINATE, &status,
2782 &path_contains_wcard);
2783 if (!NT_STATUS_IS_OK(status)) {
2784 reply_nterror(req, status);
2785 goto out;
2788 status = filename_convert(ctx, conn,
2789 req->flags2 & FLAGS2_DFS_PATHNAMES,
2790 name,
2791 UCF_COND_ALLOW_WCARD_LCOMP,
2792 &path_contains_wcard,
2793 &smb_fname);
2794 if (!NT_STATUS_IS_OK(status)) {
2795 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2796 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2797 ERRSRV, ERRbadpath);
2798 goto out;
2800 reply_nterror(req, status);
2801 goto out;
2804 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2806 status = unlink_internals(conn, req, dirtype, smb_fname,
2807 path_contains_wcard);
2808 if (!NT_STATUS_IS_OK(status)) {
2809 if (open_was_deferred(req->sconn, req->mid)) {
2810 /* We have re-scheduled this call. */
2811 goto out;
2813 reply_nterror(req, status);
2814 goto out;
2817 reply_outbuf(req, 0, 0);
2818 out:
2819 TALLOC_FREE(smb_fname);
2820 END_PROFILE(SMBunlink);
2821 return;
2824 /****************************************************************************
2825 Fail for readbraw.
2826 ****************************************************************************/
2828 static void fail_readraw(void)
2830 const char *errstr = talloc_asprintf(talloc_tos(),
2831 "FAIL ! reply_readbraw: socket write fail (%s)",
2832 strerror(errno));
2833 if (!errstr) {
2834 errstr = "";
2836 exit_server_cleanly(errstr);
2839 /****************************************************************************
2840 Fake (read/write) sendfile. Returns -1 on read or write fail.
2841 ****************************************************************************/
2843 ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread)
2845 size_t bufsize;
2846 size_t tosend = nread;
2847 char *buf;
2849 if (nread == 0) {
2850 return 0;
2853 bufsize = MIN(nread, 65536);
2855 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2856 return -1;
2859 while (tosend > 0) {
2860 ssize_t ret;
2861 size_t cur_read;
2863 if (tosend > bufsize) {
2864 cur_read = bufsize;
2865 } else {
2866 cur_read = tosend;
2868 ret = read_file(fsp,buf,startpos,cur_read);
2869 if (ret == -1) {
2870 SAFE_FREE(buf);
2871 return -1;
2874 /* If we had a short read, fill with zeros. */
2875 if (ret < cur_read) {
2876 memset(buf + ret, '\0', cur_read - ret);
2879 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2880 != cur_read) {
2881 char addr[INET6_ADDRSTRLEN];
2883 * Try and give an error message saying what
2884 * client failed.
2886 DEBUG(0, ("write_data failed for client %s. "
2887 "Error %s\n",
2888 get_peer_addr(fsp->conn->sconn->sock, addr,
2889 sizeof(addr)),
2890 strerror(errno)));
2891 SAFE_FREE(buf);
2892 return -1;
2894 tosend -= cur_read;
2895 startpos += cur_read;
2898 SAFE_FREE(buf);
2899 return (ssize_t)nread;
2902 /****************************************************************************
2903 Deal with the case of sendfile reading less bytes from the file than
2904 requested. Fill with zeros (all we can do).
2905 ****************************************************************************/
2907 void sendfile_short_send(files_struct *fsp,
2908 ssize_t nread,
2909 size_t headersize,
2910 size_t smb_maxcnt)
2912 #define SHORT_SEND_BUFSIZE 1024
2913 if (nread < headersize) {
2914 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2915 "header for file %s (%s). Terminating\n",
2916 fsp_str_dbg(fsp), strerror(errno)));
2917 exit_server_cleanly("sendfile_short_send failed");
2920 nread -= headersize;
2922 if (nread < smb_maxcnt) {
2923 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2924 if (!buf) {
2925 exit_server_cleanly("sendfile_short_send: "
2926 "malloc failed");
2929 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2930 "with zeros !\n", fsp_str_dbg(fsp)));
2932 while (nread < smb_maxcnt) {
2934 * We asked for the real file size and told sendfile
2935 * to not go beyond the end of the file. But it can
2936 * happen that in between our fstat call and the
2937 * sendfile call the file was truncated. This is very
2938 * bad because we have already announced the larger
2939 * number of bytes to the client.
2941 * The best we can do now is to send 0-bytes, just as
2942 * a read from a hole in a sparse file would do.
2944 * This should happen rarely enough that I don't care
2945 * about efficiency here :-)
2947 size_t to_write;
2949 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2950 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2951 != to_write) {
2952 char addr[INET6_ADDRSTRLEN];
2954 * Try and give an error message saying what
2955 * client failed.
2957 DEBUG(0, ("write_data failed for client %s. "
2958 "Error %s\n",
2959 get_peer_addr(
2960 fsp->conn->sconn->sock, addr,
2961 sizeof(addr)),
2962 strerror(errno)));
2963 exit_server_cleanly("sendfile_short_send: "
2964 "write_data failed");
2966 nread += to_write;
2968 SAFE_FREE(buf);
2972 /****************************************************************************
2973 Return a readbraw error (4 bytes of zero).
2974 ****************************************************************************/
2976 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2978 char header[4];
2980 SIVAL(header,0,0);
2982 smbd_lock_socket(sconn);
2983 if (write_data(sconn->sock,header,4) != 4) {
2984 char addr[INET6_ADDRSTRLEN];
2986 * Try and give an error message saying what
2987 * client failed.
2989 DEBUG(0, ("write_data failed for client %s. "
2990 "Error %s\n",
2991 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2992 strerror(errno)));
2994 fail_readraw();
2996 smbd_unlock_socket(sconn);
2999 /****************************************************************************
3000 Use sendfile in readbraw.
3001 ****************************************************************************/
3003 static void send_file_readbraw(connection_struct *conn,
3004 struct smb_request *req,
3005 files_struct *fsp,
3006 off_t startpos,
3007 size_t nread,
3008 ssize_t mincount)
3010 struct smbd_server_connection *sconn = req->sconn;
3011 char *outbuf = NULL;
3012 ssize_t ret=0;
3015 * We can only use sendfile on a non-chained packet
3016 * but we can use on a non-oplocked file. tridge proved this
3017 * on a train in Germany :-). JRA.
3018 * reply_readbraw has already checked the length.
3021 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3022 (fsp->wcp == NULL) &&
3023 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3024 ssize_t sendfile_read = -1;
3025 char header[4];
3026 DATA_BLOB header_blob;
3028 _smb_setlen(header,nread);
3029 header_blob = data_blob_const(header, 4);
3031 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3032 &header_blob, startpos,
3033 nread);
3034 if (sendfile_read == -1) {
3035 /* Returning ENOSYS means no data at all was sent.
3036 * Do this as a normal read. */
3037 if (errno == ENOSYS) {
3038 goto normal_readbraw;
3042 * Special hack for broken Linux with no working sendfile. If we
3043 * return EINTR we sent the header but not the rest of the data.
3044 * Fake this up by doing read/write calls.
3046 if (errno == EINTR) {
3047 /* Ensure we don't do this again. */
3048 set_use_sendfile(SNUM(conn), False);
3049 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3051 if (fake_sendfile(fsp, startpos, nread) == -1) {
3052 DEBUG(0,("send_file_readbraw: "
3053 "fake_sendfile failed for "
3054 "file %s (%s).\n",
3055 fsp_str_dbg(fsp),
3056 strerror(errno)));
3057 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3059 return;
3062 DEBUG(0,("send_file_readbraw: sendfile failed for "
3063 "file %s (%s). Terminating\n",
3064 fsp_str_dbg(fsp), strerror(errno)));
3065 exit_server_cleanly("send_file_readbraw sendfile failed");
3066 } else if (sendfile_read == 0) {
3068 * Some sendfile implementations return 0 to indicate
3069 * that there was a short read, but nothing was
3070 * actually written to the socket. In this case,
3071 * fallback to the normal read path so the header gets
3072 * the correct byte count.
3074 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3075 "bytes falling back to the normal read: "
3076 "%s\n", fsp_str_dbg(fsp)));
3077 goto normal_readbraw;
3080 /* Deal with possible short send. */
3081 if (sendfile_read != 4+nread) {
3082 sendfile_short_send(fsp, sendfile_read, 4, nread);
3084 return;
3087 normal_readbraw:
3089 outbuf = talloc_array(NULL, char, nread+4);
3090 if (!outbuf) {
3091 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3092 (unsigned)(nread+4)));
3093 reply_readbraw_error(sconn);
3094 return;
3097 if (nread > 0) {
3098 ret = read_file(fsp,outbuf+4,startpos,nread);
3099 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3100 if (ret < mincount)
3101 ret = 0;
3102 #else
3103 if (ret < nread)
3104 ret = 0;
3105 #endif
3108 _smb_setlen(outbuf,ret);
3109 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3110 char addr[INET6_ADDRSTRLEN];
3112 * Try and give an error message saying what
3113 * client failed.
3115 DEBUG(0, ("write_data failed for client %s. "
3116 "Error %s\n",
3117 get_peer_addr(fsp->conn->sconn->sock, addr,
3118 sizeof(addr)),
3119 strerror(errno)));
3121 fail_readraw();
3124 TALLOC_FREE(outbuf);
3127 /****************************************************************************
3128 Reply to a readbraw (core+ protocol).
3129 ****************************************************************************/
3131 void reply_readbraw(struct smb_request *req)
3133 connection_struct *conn = req->conn;
3134 struct smbd_server_connection *sconn = req->sconn;
3135 ssize_t maxcount,mincount;
3136 size_t nread = 0;
3137 off_t startpos;
3138 files_struct *fsp;
3139 struct lock_struct lock;
3140 off_t size = 0;
3142 START_PROFILE(SMBreadbraw);
3144 if (srv_is_signing_active(sconn) ||
3145 is_encrypted_packet(sconn, req->inbuf)) {
3146 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3147 "raw reads/writes are disallowed.");
3150 if (req->wct < 8) {
3151 reply_readbraw_error(sconn);
3152 END_PROFILE(SMBreadbraw);
3153 return;
3156 if (sconn->smb1.echo_handler.trusted_fde) {
3157 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3158 "'async smb echo handler = yes'\n"));
3159 reply_readbraw_error(sconn);
3160 END_PROFILE(SMBreadbraw);
3161 return;
3165 * Special check if an oplock break has been issued
3166 * and the readraw request croses on the wire, we must
3167 * return a zero length response here.
3170 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3173 * We have to do a check_fsp by hand here, as
3174 * we must always return 4 zero bytes on error,
3175 * not a NTSTATUS.
3178 if (!fsp || !conn || conn != fsp->conn ||
3179 req->vuid != fsp->vuid ||
3180 fsp->is_directory || fsp->fh->fd == -1) {
3182 * fsp could be NULL here so use the value from the packet. JRA.
3184 DEBUG(3,("reply_readbraw: fnum %d not valid "
3185 "- cache prime?\n",
3186 (int)SVAL(req->vwv+0, 0)));
3187 reply_readbraw_error(sconn);
3188 END_PROFILE(SMBreadbraw);
3189 return;
3192 /* Do a "by hand" version of CHECK_READ. */
3193 if (!(fsp->can_read ||
3194 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3195 (fsp->access_mask & FILE_EXECUTE)))) {
3196 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3197 (int)SVAL(req->vwv+0, 0)));
3198 reply_readbraw_error(sconn);
3199 END_PROFILE(SMBreadbraw);
3200 return;
3203 flush_write_cache(fsp, READRAW_FLUSH);
3205 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3206 if(req->wct == 10) {
3208 * This is a large offset (64 bit) read.
3211 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3213 if(startpos < 0) {
3214 DEBUG(0,("reply_readbraw: negative 64 bit "
3215 "readraw offset (%.0f) !\n",
3216 (double)startpos ));
3217 reply_readbraw_error(sconn);
3218 END_PROFILE(SMBreadbraw);
3219 return;
3223 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3224 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3226 /* ensure we don't overrun the packet size */
3227 maxcount = MIN(65535,maxcount);
3229 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3230 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3231 &lock);
3233 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3234 reply_readbraw_error(sconn);
3235 END_PROFILE(SMBreadbraw);
3236 return;
3239 if (fsp_stat(fsp) == 0) {
3240 size = fsp->fsp_name->st.st_ex_size;
3243 if (startpos >= size) {
3244 nread = 0;
3245 } else {
3246 nread = MIN(maxcount,(size - startpos));
3249 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3250 if (nread < mincount)
3251 nread = 0;
3252 #endif
3254 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3255 "min=%lu nread=%lu\n",
3256 fsp->fnum, (double)startpos,
3257 (unsigned long)maxcount,
3258 (unsigned long)mincount,
3259 (unsigned long)nread ) );
3261 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3263 DEBUG(5,("reply_readbraw finished\n"));
3265 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3267 END_PROFILE(SMBreadbraw);
3268 return;
3271 #undef DBGC_CLASS
3272 #define DBGC_CLASS DBGC_LOCKING
3274 /****************************************************************************
3275 Reply to a lockread (core+ protocol).
3276 ****************************************************************************/
3278 void reply_lockread(struct smb_request *req)
3280 connection_struct *conn = req->conn;
3281 ssize_t nread = -1;
3282 char *data;
3283 off_t startpos;
3284 size_t numtoread;
3285 NTSTATUS status;
3286 files_struct *fsp;
3287 struct byte_range_lock *br_lck = NULL;
3288 char *p = NULL;
3289 struct smbd_server_connection *sconn = req->sconn;
3291 START_PROFILE(SMBlockread);
3293 if (req->wct < 5) {
3294 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3295 END_PROFILE(SMBlockread);
3296 return;
3299 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3301 if (!check_fsp(conn, req, fsp)) {
3302 END_PROFILE(SMBlockread);
3303 return;
3306 if (!CHECK_READ(fsp,req)) {
3307 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3308 END_PROFILE(SMBlockread);
3309 return;
3312 numtoread = SVAL(req->vwv+1, 0);
3313 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3315 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3317 reply_outbuf(req, 5, numtoread + 3);
3319 data = smb_buf(req->outbuf) + 3;
3322 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3323 * protocol request that predates the read/write lock concept.
3324 * Thus instead of asking for a read lock here we need to ask
3325 * for a write lock. JRA.
3326 * Note that the requested lock size is unaffected by max_recv.
3329 br_lck = do_lock(req->sconn->msg_ctx,
3330 fsp,
3331 (uint64_t)req->smbpid,
3332 (uint64_t)numtoread,
3333 (uint64_t)startpos,
3334 WRITE_LOCK,
3335 WINDOWS_LOCK,
3336 False, /* Non-blocking lock. */
3337 &status,
3338 NULL,
3339 NULL);
3340 TALLOC_FREE(br_lck);
3342 if (NT_STATUS_V(status)) {
3343 reply_nterror(req, status);
3344 END_PROFILE(SMBlockread);
3345 return;
3349 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3352 if (numtoread > sconn->smb1.negprot.max_recv) {
3353 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3354 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3355 (unsigned int)numtoread,
3356 (unsigned int)sconn->smb1.negprot.max_recv));
3357 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3359 nread = read_file(fsp,data,startpos,numtoread);
3361 if (nread < 0) {
3362 reply_nterror(req, map_nt_error_from_unix(errno));
3363 END_PROFILE(SMBlockread);
3364 return;
3367 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3369 SSVAL(req->outbuf,smb_vwv0,nread);
3370 SSVAL(req->outbuf,smb_vwv5,nread+3);
3371 p = smb_buf(req->outbuf);
3372 SCVAL(p,0,0); /* pad byte. */
3373 SSVAL(p,1,nread);
3375 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3376 fsp->fnum, (int)numtoread, (int)nread));
3378 END_PROFILE(SMBlockread);
3379 return;
3382 #undef DBGC_CLASS
3383 #define DBGC_CLASS DBGC_ALL
3385 /****************************************************************************
3386 Reply to a read.
3387 ****************************************************************************/
3389 void reply_read(struct smb_request *req)
3391 connection_struct *conn = req->conn;
3392 size_t numtoread;
3393 ssize_t nread = 0;
3394 char *data;
3395 off_t startpos;
3396 int outsize = 0;
3397 files_struct *fsp;
3398 struct lock_struct lock;
3399 struct smbd_server_connection *sconn = req->sconn;
3401 START_PROFILE(SMBread);
3403 if (req->wct < 3) {
3404 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3405 END_PROFILE(SMBread);
3406 return;
3409 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3411 if (!check_fsp(conn, req, fsp)) {
3412 END_PROFILE(SMBread);
3413 return;
3416 if (!CHECK_READ(fsp,req)) {
3417 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3418 END_PROFILE(SMBread);
3419 return;
3422 numtoread = SVAL(req->vwv+1, 0);
3423 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3425 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3428 * The requested read size cannot be greater than max_recv. JRA.
3430 if (numtoread > sconn->smb1.negprot.max_recv) {
3431 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3432 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3433 (unsigned int)numtoread,
3434 (unsigned int)sconn->smb1.negprot.max_recv));
3435 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3438 reply_outbuf(req, 5, numtoread+3);
3440 data = smb_buf(req->outbuf) + 3;
3442 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3443 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3444 &lock);
3446 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3447 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3448 END_PROFILE(SMBread);
3449 return;
3452 if (numtoread > 0)
3453 nread = read_file(fsp,data,startpos,numtoread);
3455 if (nread < 0) {
3456 reply_nterror(req, map_nt_error_from_unix(errno));
3457 goto strict_unlock;
3460 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3462 SSVAL(req->outbuf,smb_vwv0,nread);
3463 SSVAL(req->outbuf,smb_vwv5,nread+3);
3464 SCVAL(smb_buf(req->outbuf),0,1);
3465 SSVAL(smb_buf(req->outbuf),1,nread);
3467 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3468 fsp->fnum, (int)numtoread, (int)nread ) );
3470 strict_unlock:
3471 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3473 END_PROFILE(SMBread);
3474 return;
3477 /****************************************************************************
3478 Setup readX header.
3479 ****************************************************************************/
3481 static int setup_readX_header(struct smb_request *req, char *outbuf,
3482 size_t smb_maxcnt)
3484 int outsize;
3486 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3488 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3490 SCVAL(outbuf,smb_vwv0,0xFF);
3491 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3492 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3493 SSVAL(outbuf,smb_vwv6,
3494 (smb_wct - 4) /* offset from smb header to wct */
3495 + 1 /* the wct field */
3496 + 12 * sizeof(uint16_t) /* vwv */
3497 + 2); /* the buflen field */
3498 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3499 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3500 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3501 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3502 return outsize;
3505 /****************************************************************************
3506 Reply to a read and X - possibly using sendfile.
3507 ****************************************************************************/
3509 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3510 files_struct *fsp, off_t startpos,
3511 size_t smb_maxcnt)
3513 ssize_t nread = -1;
3514 struct lock_struct lock;
3515 int saved_errno = 0;
3517 if(fsp_stat(fsp) == -1) {
3518 reply_nterror(req, map_nt_error_from_unix(errno));
3519 return;
3522 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3523 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3524 &lock);
3526 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3527 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3528 return;
3531 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3532 (startpos > fsp->fsp_name->st.st_ex_size)
3533 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3535 * We already know that we would do a short read, so don't
3536 * try the sendfile() path.
3538 goto nosendfile_read;
3542 * We can only use sendfile on a non-chained packet
3543 * but we can use on a non-oplocked file. tridge proved this
3544 * on a train in Germany :-). JRA.
3547 if (!req_is_in_chain(req) &&
3548 !is_encrypted_packet(req->sconn, req->inbuf) &&
3549 (fsp->base_fsp == NULL) &&
3550 (fsp->wcp == NULL) &&
3551 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3552 uint8 headerbuf[smb_size + 12 * 2];
3553 DATA_BLOB header;
3556 * Set up the packet header before send. We
3557 * assume here the sendfile will work (get the
3558 * correct amount of data).
3561 header = data_blob_const(headerbuf, sizeof(headerbuf));
3563 construct_reply_common_req(req, (char *)headerbuf);
3564 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3566 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3567 startpos, smb_maxcnt);
3568 if (nread == -1) {
3569 /* Returning ENOSYS means no data at all was sent.
3570 Do this as a normal read. */
3571 if (errno == ENOSYS) {
3572 goto normal_read;
3576 * Special hack for broken Linux with no working sendfile. If we
3577 * return EINTR we sent the header but not the rest of the data.
3578 * Fake this up by doing read/write calls.
3581 if (errno == EINTR) {
3582 /* Ensure we don't do this again. */
3583 set_use_sendfile(SNUM(conn), False);
3584 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3585 nread = fake_sendfile(fsp, startpos,
3586 smb_maxcnt);
3587 if (nread == -1) {
3588 DEBUG(0,("send_file_readX: "
3589 "fake_sendfile failed for "
3590 "file %s (%s).\n",
3591 fsp_str_dbg(fsp),
3592 strerror(errno)));
3593 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3595 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3596 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3597 /* No outbuf here means successful sendfile. */
3598 goto strict_unlock;
3601 DEBUG(0,("send_file_readX: sendfile failed for file "
3602 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3603 strerror(errno)));
3604 exit_server_cleanly("send_file_readX sendfile failed");
3605 } else if (nread == 0) {
3607 * Some sendfile implementations return 0 to indicate
3608 * that there was a short read, but nothing was
3609 * actually written to the socket. In this case,
3610 * fallback to the normal read path so the header gets
3611 * the correct byte count.
3613 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3614 "falling back to the normal read: %s\n",
3615 fsp_str_dbg(fsp)));
3616 goto normal_read;
3619 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3620 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3622 /* Deal with possible short send. */
3623 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3624 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3626 /* No outbuf here means successful sendfile. */
3627 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3628 SMB_PERFCOUNT_END(&req->pcd);
3629 goto strict_unlock;
3632 normal_read:
3634 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3635 uint8 headerbuf[smb_size + 2*12];
3637 construct_reply_common_req(req, (char *)headerbuf);
3638 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3640 /* Send out the header. */
3641 if (write_data(req->sconn->sock, (char *)headerbuf,
3642 sizeof(headerbuf)) != sizeof(headerbuf)) {
3644 char addr[INET6_ADDRSTRLEN];
3646 * Try and give an error message saying what
3647 * client failed.
3649 DEBUG(0, ("write_data failed for client %s. "
3650 "Error %s\n",
3651 get_peer_addr(req->sconn->sock, addr,
3652 sizeof(addr)),
3653 strerror(errno)));
3655 DEBUG(0,("send_file_readX: write_data failed for file "
3656 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3657 strerror(errno)));
3658 exit_server_cleanly("send_file_readX sendfile failed");
3660 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3661 if (nread == -1) {
3662 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3663 "file %s (%s).\n", fsp_str_dbg(fsp),
3664 strerror(errno)));
3665 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3667 goto strict_unlock;
3670 nosendfile_read:
3672 reply_outbuf(req, 12, smb_maxcnt);
3673 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3674 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3676 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3677 saved_errno = errno;
3679 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3681 if (nread < 0) {
3682 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3683 return;
3686 setup_readX_header(req, (char *)req->outbuf, nread);
3688 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3689 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3690 return;
3692 strict_unlock:
3693 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3694 TALLOC_FREE(req->outbuf);
3695 return;
3698 /****************************************************************************
3699 Reply to a read and X.
3700 ****************************************************************************/
3702 void reply_read_and_X(struct smb_request *req)
3704 struct smbd_server_connection *sconn = req->sconn;
3705 connection_struct *conn = req->conn;
3706 files_struct *fsp;
3707 off_t startpos;
3708 size_t smb_maxcnt;
3709 bool big_readX = False;
3710 #if 0
3711 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3712 #endif
3714 START_PROFILE(SMBreadX);
3716 if ((req->wct != 10) && (req->wct != 12)) {
3717 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3718 return;
3721 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3722 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3723 smb_maxcnt = SVAL(req->vwv+5, 0);
3725 /* If it's an IPC, pass off the pipe handler. */
3726 if (IS_IPC(conn)) {
3727 reply_pipe_read_and_X(req);
3728 END_PROFILE(SMBreadX);
3729 return;
3732 if (!check_fsp(conn, req, fsp)) {
3733 END_PROFILE(SMBreadX);
3734 return;
3737 if (!CHECK_READ(fsp,req)) {
3738 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3739 END_PROFILE(SMBreadX);
3740 return;
3743 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_LARGE_READ_CAP) ||
3744 (get_remote_arch() == RA_SAMBA)) {
3746 * This is Samba only behavior (up to Samba 3.6)!
3748 * Windows 2008 R2 ignores the upper_size,
3749 * so we do unless unix extentions are active
3750 * or "smbclient" is talking to us.
3752 size_t upper_size = SVAL(req->vwv+7, 0);
3753 smb_maxcnt |= (upper_size<<16);
3754 if (upper_size > 1) {
3755 /* Can't do this on a chained packet. */
3756 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3757 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3758 END_PROFILE(SMBreadX);
3759 return;
3761 /* We currently don't do this on signed or sealed data. */
3762 if (srv_is_signing_active(req->sconn) ||
3763 is_encrypted_packet(req->sconn, req->inbuf)) {
3764 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3765 END_PROFILE(SMBreadX);
3766 return;
3768 /* Is there room in the reply for this data ? */
3769 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3770 reply_nterror(req,
3771 NT_STATUS_INVALID_PARAMETER);
3772 END_PROFILE(SMBreadX);
3773 return;
3775 big_readX = True;
3779 if (req->wct == 12) {
3781 * This is a large offset (64 bit) read.
3783 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
3787 if (!big_readX) {
3788 NTSTATUS status = schedule_aio_read_and_X(conn,
3789 req,
3790 fsp,
3791 startpos,
3792 smb_maxcnt);
3793 if (NT_STATUS_IS_OK(status)) {
3794 /* Read scheduled - we're done. */
3795 goto out;
3797 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3798 /* Real error - report to client. */
3799 END_PROFILE(SMBreadX);
3800 reply_nterror(req, status);
3801 return;
3803 /* NT_STATUS_RETRY - fall back to sync read. */
3806 smbd_lock_socket(req->sconn);
3807 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3808 smbd_unlock_socket(req->sconn);
3810 out:
3811 END_PROFILE(SMBreadX);
3812 return;
3815 /****************************************************************************
3816 Error replies to writebraw must have smb_wct == 1. Fix this up.
3817 ****************************************************************************/
3819 void error_to_writebrawerr(struct smb_request *req)
3821 uint8 *old_outbuf = req->outbuf;
3823 reply_outbuf(req, 1, 0);
3825 memcpy(req->outbuf, old_outbuf, smb_size);
3826 TALLOC_FREE(old_outbuf);
3829 /****************************************************************************
3830 Read 4 bytes of a smb packet and return the smb length of the packet.
3831 Store the result in the buffer. This version of the function will
3832 never return a session keepalive (length of zero).
3833 Timeout is in milliseconds.
3834 ****************************************************************************/
3836 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3837 size_t *len)
3839 uint8_t msgtype = NBSSkeepalive;
3841 while (msgtype == NBSSkeepalive) {
3842 NTSTATUS status;
3844 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3845 len);
3846 if (!NT_STATUS_IS_OK(status)) {
3847 char addr[INET6_ADDRSTRLEN];
3848 /* Try and give an error message
3849 * saying what client failed. */
3850 DEBUG(0, ("read_fd_with_timeout failed for "
3851 "client %s read error = %s.\n",
3852 get_peer_addr(fd,addr,sizeof(addr)),
3853 nt_errstr(status)));
3854 return status;
3857 msgtype = CVAL(inbuf, 0);
3860 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3861 (unsigned long)len));
3863 return NT_STATUS_OK;
3866 /****************************************************************************
3867 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3868 ****************************************************************************/
3870 void reply_writebraw(struct smb_request *req)
3872 connection_struct *conn = req->conn;
3873 char *buf = NULL;
3874 ssize_t nwritten=0;
3875 ssize_t total_written=0;
3876 size_t numtowrite=0;
3877 size_t tcount;
3878 off_t startpos;
3879 const char *data=NULL;
3880 bool write_through;
3881 files_struct *fsp;
3882 struct lock_struct lock;
3883 NTSTATUS status;
3885 START_PROFILE(SMBwritebraw);
3888 * If we ever reply with an error, it must have the SMB command
3889 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3890 * we're finished.
3892 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3894 if (srv_is_signing_active(req->sconn)) {
3895 END_PROFILE(SMBwritebraw);
3896 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3897 "raw reads/writes are disallowed.");
3900 if (req->wct < 12) {
3901 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3902 error_to_writebrawerr(req);
3903 END_PROFILE(SMBwritebraw);
3904 return;
3907 if (req->sconn->smb1.echo_handler.trusted_fde) {
3908 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3909 "'async smb echo handler = yes'\n"));
3910 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3911 error_to_writebrawerr(req);
3912 END_PROFILE(SMBwritebraw);
3913 return;
3916 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3917 if (!check_fsp(conn, req, fsp)) {
3918 error_to_writebrawerr(req);
3919 END_PROFILE(SMBwritebraw);
3920 return;
3923 if (!CHECK_WRITE(fsp)) {
3924 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3925 error_to_writebrawerr(req);
3926 END_PROFILE(SMBwritebraw);
3927 return;
3930 tcount = IVAL(req->vwv+1, 0);
3931 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3932 write_through = BITSETW(req->vwv+7,0);
3934 /* We have to deal with slightly different formats depending
3935 on whether we are using the core+ or lanman1.0 protocol */
3937 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3938 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3939 data = smb_buf_const(req->inbuf);
3940 } else {
3941 numtowrite = SVAL(req->vwv+10, 0);
3942 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3945 /* Ensure we don't write bytes past the end of this packet. */
3946 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3948 error_to_writebrawerr(req);
3949 END_PROFILE(SMBwritebraw);
3950 return;
3953 if (!fsp->print_file) {
3954 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3955 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3956 &lock);
3958 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3959 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3960 error_to_writebrawerr(req);
3961 END_PROFILE(SMBwritebraw);
3962 return;
3966 if (numtowrite>0) {
3967 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3970 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3971 "wrote=%d sync=%d\n",
3972 fsp->fnum, (double)startpos, (int)numtowrite,
3973 (int)nwritten, (int)write_through));
3975 if (nwritten < (ssize_t)numtowrite) {
3976 reply_nterror(req, NT_STATUS_DISK_FULL);
3977 error_to_writebrawerr(req);
3978 goto strict_unlock;
3981 total_written = nwritten;
3983 /* Allocate a buffer of 64k + length. */
3984 buf = talloc_array(NULL, char, 65540);
3985 if (!buf) {
3986 reply_nterror(req, NT_STATUS_NO_MEMORY);
3987 error_to_writebrawerr(req);
3988 goto strict_unlock;
3991 /* Return a SMBwritebraw message to the redirector to tell
3992 * it to send more bytes */
3994 memcpy(buf, req->inbuf, smb_size);
3995 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3996 SCVAL(buf,smb_com,SMBwritebraw);
3997 SSVALS(buf,smb_vwv0,0xFFFF);
3998 show_msg(buf);
3999 if (!srv_send_smb(req->sconn,
4000 buf,
4001 false, 0, /* no signing */
4002 IS_CONN_ENCRYPTED(conn),
4003 &req->pcd)) {
4004 exit_server_cleanly("reply_writebraw: srv_send_smb "
4005 "failed.");
4008 /* Now read the raw data into the buffer and write it */
4009 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4010 &numtowrite);
4011 if (!NT_STATUS_IS_OK(status)) {
4012 exit_server_cleanly("secondary writebraw failed");
4015 /* Set up outbuf to return the correct size */
4016 reply_outbuf(req, 1, 0);
4018 if (numtowrite != 0) {
4020 if (numtowrite > 0xFFFF) {
4021 DEBUG(0,("reply_writebraw: Oversize secondary write "
4022 "raw requested (%u). Terminating\n",
4023 (unsigned int)numtowrite ));
4024 exit_server_cleanly("secondary writebraw failed");
4027 if (tcount > nwritten+numtowrite) {
4028 DEBUG(3,("reply_writebraw: Client overestimated the "
4029 "write %d %d %d\n",
4030 (int)tcount,(int)nwritten,(int)numtowrite));
4033 status = read_data(req->sconn->sock, buf+4, numtowrite);
4035 if (!NT_STATUS_IS_OK(status)) {
4036 char addr[INET6_ADDRSTRLEN];
4037 /* Try and give an error message
4038 * saying what client failed. */
4039 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4040 "raw read failed (%s) for client %s. "
4041 "Terminating\n", nt_errstr(status),
4042 get_peer_addr(req->sconn->sock, addr,
4043 sizeof(addr))));
4044 exit_server_cleanly("secondary writebraw failed");
4047 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4048 if (nwritten == -1) {
4049 TALLOC_FREE(buf);
4050 reply_nterror(req, map_nt_error_from_unix(errno));
4051 error_to_writebrawerr(req);
4052 goto strict_unlock;
4055 if (nwritten < (ssize_t)numtowrite) {
4056 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4057 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4060 if (nwritten > 0) {
4061 total_written += nwritten;
4065 TALLOC_FREE(buf);
4066 SSVAL(req->outbuf,smb_vwv0,total_written);
4068 status = sync_file(conn, fsp, write_through);
4069 if (!NT_STATUS_IS_OK(status)) {
4070 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4071 fsp_str_dbg(fsp), nt_errstr(status)));
4072 reply_nterror(req, status);
4073 error_to_writebrawerr(req);
4074 goto strict_unlock;
4077 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4078 "wrote=%d\n",
4079 fsp->fnum, (double)startpos, (int)numtowrite,
4080 (int)total_written));
4082 if (!fsp->print_file) {
4083 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4086 /* We won't return a status if write through is not selected - this
4087 * follows what WfWg does */
4088 END_PROFILE(SMBwritebraw);
4090 if (!write_through && total_written==tcount) {
4092 #if RABBIT_PELLET_FIX
4094 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4095 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4096 * JRA.
4098 if (!send_keepalive(req->sconn->sock)) {
4099 exit_server_cleanly("reply_writebraw: send of "
4100 "keepalive failed");
4102 #endif
4103 TALLOC_FREE(req->outbuf);
4105 return;
4107 strict_unlock:
4108 if (!fsp->print_file) {
4109 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4112 END_PROFILE(SMBwritebraw);
4113 return;
4116 #undef DBGC_CLASS
4117 #define DBGC_CLASS DBGC_LOCKING
4119 /****************************************************************************
4120 Reply to a writeunlock (core+).
4121 ****************************************************************************/
4123 void reply_writeunlock(struct smb_request *req)
4125 connection_struct *conn = req->conn;
4126 ssize_t nwritten = -1;
4127 size_t numtowrite;
4128 off_t startpos;
4129 const char *data;
4130 NTSTATUS status = NT_STATUS_OK;
4131 files_struct *fsp;
4132 struct lock_struct lock;
4133 int saved_errno = 0;
4135 START_PROFILE(SMBwriteunlock);
4137 if (req->wct < 5) {
4138 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4139 END_PROFILE(SMBwriteunlock);
4140 return;
4143 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4145 if (!check_fsp(conn, req, fsp)) {
4146 END_PROFILE(SMBwriteunlock);
4147 return;
4150 if (!CHECK_WRITE(fsp)) {
4151 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4152 END_PROFILE(SMBwriteunlock);
4153 return;
4156 numtowrite = SVAL(req->vwv+1, 0);
4157 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4158 data = (const char *)req->buf + 3;
4160 if (!fsp->print_file && numtowrite > 0) {
4161 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4162 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4163 &lock);
4165 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4166 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4167 END_PROFILE(SMBwriteunlock);
4168 return;
4172 /* The special X/Open SMB protocol handling of
4173 zero length writes is *NOT* done for
4174 this call */
4175 if(numtowrite == 0) {
4176 nwritten = 0;
4177 } else {
4178 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4179 saved_errno = errno;
4182 status = sync_file(conn, fsp, False /* write through */);
4183 if (!NT_STATUS_IS_OK(status)) {
4184 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4185 fsp_str_dbg(fsp), nt_errstr(status)));
4186 reply_nterror(req, status);
4187 goto strict_unlock;
4190 if(nwritten < 0) {
4191 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4192 goto strict_unlock;
4195 if((nwritten < numtowrite) && (numtowrite != 0)) {
4196 reply_nterror(req, NT_STATUS_DISK_FULL);
4197 goto strict_unlock;
4200 if (numtowrite && !fsp->print_file) {
4201 status = do_unlock(req->sconn->msg_ctx,
4202 fsp,
4203 (uint64_t)req->smbpid,
4204 (uint64_t)numtowrite,
4205 (uint64_t)startpos,
4206 WINDOWS_LOCK);
4208 if (NT_STATUS_V(status)) {
4209 reply_nterror(req, status);
4210 goto strict_unlock;
4214 reply_outbuf(req, 1, 0);
4216 SSVAL(req->outbuf,smb_vwv0,nwritten);
4218 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4219 fsp->fnum, (int)numtowrite, (int)nwritten));
4221 strict_unlock:
4222 if (numtowrite && !fsp->print_file) {
4223 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4226 END_PROFILE(SMBwriteunlock);
4227 return;
4230 #undef DBGC_CLASS
4231 #define DBGC_CLASS DBGC_ALL
4233 /****************************************************************************
4234 Reply to a write.
4235 ****************************************************************************/
4237 void reply_write(struct smb_request *req)
4239 connection_struct *conn = req->conn;
4240 size_t numtowrite;
4241 ssize_t nwritten = -1;
4242 off_t startpos;
4243 const char *data;
4244 files_struct *fsp;
4245 struct lock_struct lock;
4246 NTSTATUS status;
4247 int saved_errno = 0;
4249 START_PROFILE(SMBwrite);
4251 if (req->wct < 5) {
4252 END_PROFILE(SMBwrite);
4253 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4254 return;
4257 /* If it's an IPC, pass off the pipe handler. */
4258 if (IS_IPC(conn)) {
4259 reply_pipe_write(req);
4260 END_PROFILE(SMBwrite);
4261 return;
4264 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4266 if (!check_fsp(conn, req, fsp)) {
4267 END_PROFILE(SMBwrite);
4268 return;
4271 if (!CHECK_WRITE(fsp)) {
4272 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4273 END_PROFILE(SMBwrite);
4274 return;
4277 numtowrite = SVAL(req->vwv+1, 0);
4278 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4279 data = (const char *)req->buf + 3;
4281 if (!fsp->print_file) {
4282 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4283 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4284 &lock);
4286 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4287 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4288 END_PROFILE(SMBwrite);
4289 return;
4294 * X/Open SMB protocol says that if smb_vwv1 is
4295 * zero then the file size should be extended or
4296 * truncated to the size given in smb_vwv[2-3].
4299 if(numtowrite == 0) {
4301 * This is actually an allocate call, and set EOF. JRA.
4303 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4304 if (nwritten < 0) {
4305 reply_nterror(req, NT_STATUS_DISK_FULL);
4306 goto strict_unlock;
4308 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4309 if (nwritten < 0) {
4310 reply_nterror(req, NT_STATUS_DISK_FULL);
4311 goto strict_unlock;
4313 trigger_write_time_update_immediate(fsp);
4314 } else {
4315 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4318 status = sync_file(conn, fsp, False);
4319 if (!NT_STATUS_IS_OK(status)) {
4320 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4321 fsp_str_dbg(fsp), nt_errstr(status)));
4322 reply_nterror(req, status);
4323 goto strict_unlock;
4326 if(nwritten < 0) {
4327 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4328 goto strict_unlock;
4331 if((nwritten == 0) && (numtowrite != 0)) {
4332 reply_nterror(req, NT_STATUS_DISK_FULL);
4333 goto strict_unlock;
4336 reply_outbuf(req, 1, 0);
4338 SSVAL(req->outbuf,smb_vwv0,nwritten);
4340 if (nwritten < (ssize_t)numtowrite) {
4341 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4342 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4345 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4347 strict_unlock:
4348 if (!fsp->print_file) {
4349 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4352 END_PROFILE(SMBwrite);
4353 return;
4356 /****************************************************************************
4357 Ensure a buffer is a valid writeX for recvfile purposes.
4358 ****************************************************************************/
4360 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4361 (2*14) + /* word count (including bcc) */ \
4362 1 /* pad byte */)
4364 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4365 const uint8_t *inbuf)
4367 size_t numtowrite;
4368 connection_struct *conn = NULL;
4369 unsigned int doff = 0;
4370 size_t len = smb_len_large(inbuf);
4372 if (is_encrypted_packet(sconn, inbuf)) {
4373 /* Can't do this on encrypted
4374 * connections. */
4375 return false;
4378 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4379 return false;
4382 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4383 CVAL(inbuf,smb_wct) != 14) {
4384 DEBUG(10,("is_valid_writeX_buffer: chained or "
4385 "invalid word length.\n"));
4386 return false;
4389 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4390 if (conn == NULL) {
4391 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4392 return false;
4394 if (IS_IPC(conn)) {
4395 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4396 return false;
4398 if (IS_PRINT(conn)) {
4399 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4400 return false;
4402 doff = SVAL(inbuf,smb_vwv11);
4404 numtowrite = SVAL(inbuf,smb_vwv10);
4406 if (len > doff && len - doff > 0xFFFF) {
4407 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4410 if (numtowrite == 0) {
4411 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4412 return false;
4415 /* Ensure the sizes match up. */
4416 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4417 /* no pad byte...old smbclient :-( */
4418 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4419 (unsigned int)doff,
4420 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4421 return false;
4424 if (len - doff != numtowrite) {
4425 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4426 "len = %u, doff = %u, numtowrite = %u\n",
4427 (unsigned int)len,
4428 (unsigned int)doff,
4429 (unsigned int)numtowrite ));
4430 return false;
4433 DEBUG(10,("is_valid_writeX_buffer: true "
4434 "len = %u, doff = %u, numtowrite = %u\n",
4435 (unsigned int)len,
4436 (unsigned int)doff,
4437 (unsigned int)numtowrite ));
4439 return true;
4442 /****************************************************************************
4443 Reply to a write and X.
4444 ****************************************************************************/
4446 void reply_write_and_X(struct smb_request *req)
4448 connection_struct *conn = req->conn;
4449 files_struct *fsp;
4450 struct lock_struct lock;
4451 off_t startpos;
4452 size_t numtowrite;
4453 bool write_through;
4454 ssize_t nwritten;
4455 unsigned int smb_doff;
4456 unsigned int smblen;
4457 const char *data;
4458 NTSTATUS status;
4459 int saved_errno = 0;
4461 START_PROFILE(SMBwriteX);
4463 if ((req->wct != 12) && (req->wct != 14)) {
4464 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4465 goto out;
4468 numtowrite = SVAL(req->vwv+10, 0);
4469 smb_doff = SVAL(req->vwv+11, 0);
4470 smblen = smb_len(req->inbuf);
4472 if (req->unread_bytes > 0xFFFF ||
4473 (smblen > smb_doff &&
4474 smblen - smb_doff > 0xFFFF)) {
4475 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4478 if (req->unread_bytes) {
4479 /* Can't do a recvfile write on IPC$ */
4480 if (IS_IPC(conn)) {
4481 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4482 goto out;
4484 if (numtowrite != req->unread_bytes) {
4485 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4486 goto out;
4488 } else {
4489 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4490 smb_doff + numtowrite > smblen) {
4491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4492 goto out;
4496 /* If it's an IPC, pass off the pipe handler. */
4497 if (IS_IPC(conn)) {
4498 if (req->unread_bytes) {
4499 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4500 goto out;
4502 reply_pipe_write_and_X(req);
4503 goto out;
4506 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4507 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4508 write_through = BITSETW(req->vwv+7,0);
4510 if (!check_fsp(conn, req, fsp)) {
4511 goto out;
4514 if (!CHECK_WRITE(fsp)) {
4515 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4516 goto out;
4519 data = smb_base(req->inbuf) + smb_doff;
4521 if(req->wct == 14) {
4523 * This is a large offset (64 bit) write.
4525 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4529 /* X/Open SMB protocol says that, unlike SMBwrite
4530 if the length is zero then NO truncation is
4531 done, just a write of zero. To truncate a file,
4532 use SMBwrite. */
4534 if(numtowrite == 0) {
4535 nwritten = 0;
4536 } else {
4537 if (req->unread_bytes == 0) {
4538 status = schedule_aio_write_and_X(conn,
4539 req,
4540 fsp,
4541 data,
4542 startpos,
4543 numtowrite);
4545 if (NT_STATUS_IS_OK(status)) {
4546 /* write scheduled - we're done. */
4547 goto out;
4549 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4550 /* Real error - report to client. */
4551 reply_nterror(req, status);
4552 goto out;
4554 /* NT_STATUS_RETRY - fall through to sync write. */
4557 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4558 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4559 &lock);
4561 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4562 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4563 goto out;
4566 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4567 saved_errno = errno;
4569 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4572 if(nwritten < 0) {
4573 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4574 goto out;
4577 if((nwritten == 0) && (numtowrite != 0)) {
4578 reply_nterror(req, NT_STATUS_DISK_FULL);
4579 goto out;
4582 reply_outbuf(req, 6, 0);
4583 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4584 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4585 SSVAL(req->outbuf,smb_vwv2,nwritten);
4586 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4588 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4589 fsp->fnum, (int)numtowrite, (int)nwritten));
4591 status = sync_file(conn, fsp, write_through);
4592 if (!NT_STATUS_IS_OK(status)) {
4593 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4594 fsp_str_dbg(fsp), nt_errstr(status)));
4595 reply_nterror(req, status);
4596 goto out;
4599 END_PROFILE(SMBwriteX);
4600 return;
4602 out:
4603 if (req->unread_bytes) {
4604 /* writeX failed. drain socket. */
4605 if (drain_socket(req->sconn->sock, req->unread_bytes) !=
4606 req->unread_bytes) {
4607 smb_panic("failed to drain pending bytes");
4609 req->unread_bytes = 0;
4612 END_PROFILE(SMBwriteX);
4613 return;
4616 /****************************************************************************
4617 Reply to a lseek.
4618 ****************************************************************************/
4620 void reply_lseek(struct smb_request *req)
4622 connection_struct *conn = req->conn;
4623 off_t startpos;
4624 off_t res= -1;
4625 int mode,umode;
4626 files_struct *fsp;
4628 START_PROFILE(SMBlseek);
4630 if (req->wct < 4) {
4631 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4632 END_PROFILE(SMBlseek);
4633 return;
4636 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4638 if (!check_fsp(conn, req, fsp)) {
4639 return;
4642 flush_write_cache(fsp, SEEK_FLUSH);
4644 mode = SVAL(req->vwv+1, 0) & 3;
4645 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4646 startpos = (off_t)IVALS(req->vwv+2, 0);
4648 switch (mode) {
4649 case 0:
4650 umode = SEEK_SET;
4651 res = startpos;
4652 break;
4653 case 1:
4654 umode = SEEK_CUR;
4655 res = fsp->fh->pos + startpos;
4656 break;
4657 case 2:
4658 umode = SEEK_END;
4659 break;
4660 default:
4661 umode = SEEK_SET;
4662 res = startpos;
4663 break;
4666 if (umode == SEEK_END) {
4667 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4668 if(errno == EINVAL) {
4669 off_t current_pos = startpos;
4671 if(fsp_stat(fsp) == -1) {
4672 reply_nterror(req,
4673 map_nt_error_from_unix(errno));
4674 END_PROFILE(SMBlseek);
4675 return;
4678 current_pos += fsp->fsp_name->st.st_ex_size;
4679 if(current_pos < 0)
4680 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4684 if(res == -1) {
4685 reply_nterror(req, map_nt_error_from_unix(errno));
4686 END_PROFILE(SMBlseek);
4687 return;
4691 fsp->fh->pos = res;
4693 reply_outbuf(req, 2, 0);
4694 SIVAL(req->outbuf,smb_vwv0,res);
4696 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4697 fsp->fnum, (double)startpos, (double)res, mode));
4699 END_PROFILE(SMBlseek);
4700 return;
4703 /****************************************************************************
4704 Reply to a flush.
4705 ****************************************************************************/
4707 void reply_flush(struct smb_request *req)
4709 connection_struct *conn = req->conn;
4710 uint16 fnum;
4711 files_struct *fsp;
4713 START_PROFILE(SMBflush);
4715 if (req->wct < 1) {
4716 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4717 return;
4720 fnum = SVAL(req->vwv+0, 0);
4721 fsp = file_fsp(req, fnum);
4723 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4724 return;
4727 if (!fsp) {
4728 file_sync_all(conn);
4729 } else {
4730 NTSTATUS status = sync_file(conn, fsp, True);
4731 if (!NT_STATUS_IS_OK(status)) {
4732 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4733 fsp_str_dbg(fsp), nt_errstr(status)));
4734 reply_nterror(req, status);
4735 END_PROFILE(SMBflush);
4736 return;
4740 reply_outbuf(req, 0, 0);
4742 DEBUG(3,("flush\n"));
4743 END_PROFILE(SMBflush);
4744 return;
4747 /****************************************************************************
4748 Reply to a exit.
4749 conn POINTER CAN BE NULL HERE !
4750 ****************************************************************************/
4752 void reply_exit(struct smb_request *req)
4754 START_PROFILE(SMBexit);
4756 file_close_pid(req->sconn, req->smbpid, req->vuid);
4758 reply_outbuf(req, 0, 0);
4760 DEBUG(3,("exit\n"));
4762 END_PROFILE(SMBexit);
4763 return;
4766 /****************************************************************************
4767 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4768 ****************************************************************************/
4770 void reply_close(struct smb_request *req)
4772 connection_struct *conn = req->conn;
4773 NTSTATUS status = NT_STATUS_OK;
4774 files_struct *fsp = NULL;
4775 START_PROFILE(SMBclose);
4777 if (req->wct < 3) {
4778 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4779 END_PROFILE(SMBclose);
4780 return;
4783 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4786 * We can only use check_fsp if we know it's not a directory.
4789 if (!check_fsp_open(conn, req, fsp)) {
4790 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4791 END_PROFILE(SMBclose);
4792 return;
4795 if(fsp->is_directory) {
4797 * Special case - close NT SMB directory handle.
4799 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4800 status = close_file(req, fsp, NORMAL_CLOSE);
4801 } else {
4802 time_t t;
4804 * Close ordinary file.
4807 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4808 fsp->fh->fd, fsp->fnum,
4809 conn->num_files_open));
4812 * Take care of any time sent in the close.
4815 t = srv_make_unix_date3(req->vwv+1);
4816 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4819 * close_file() returns the unix errno if an error
4820 * was detected on close - normally this is due to
4821 * a disk full error. If not then it was probably an I/O error.
4824 status = close_file(req, fsp, NORMAL_CLOSE);
4827 if (!NT_STATUS_IS_OK(status)) {
4828 reply_nterror(req, status);
4829 END_PROFILE(SMBclose);
4830 return;
4833 reply_outbuf(req, 0, 0);
4834 END_PROFILE(SMBclose);
4835 return;
4838 /****************************************************************************
4839 Reply to a writeclose (Core+ protocol).
4840 ****************************************************************************/
4842 void reply_writeclose(struct smb_request *req)
4844 connection_struct *conn = req->conn;
4845 size_t numtowrite;
4846 ssize_t nwritten = -1;
4847 NTSTATUS close_status = NT_STATUS_OK;
4848 off_t startpos;
4849 const char *data;
4850 struct timespec mtime;
4851 files_struct *fsp;
4852 struct lock_struct lock;
4854 START_PROFILE(SMBwriteclose);
4856 if (req->wct < 6) {
4857 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4858 END_PROFILE(SMBwriteclose);
4859 return;
4862 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4864 if (!check_fsp(conn, req, fsp)) {
4865 END_PROFILE(SMBwriteclose);
4866 return;
4868 if (!CHECK_WRITE(fsp)) {
4869 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4870 END_PROFILE(SMBwriteclose);
4871 return;
4874 numtowrite = SVAL(req->vwv+1, 0);
4875 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4876 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4877 data = (const char *)req->buf + 1;
4879 if (!fsp->print_file) {
4880 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4881 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4882 &lock);
4884 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4885 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4886 END_PROFILE(SMBwriteclose);
4887 return;
4891 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4893 set_close_write_time(fsp, mtime);
4896 * More insanity. W2K only closes the file if writelen > 0.
4897 * JRA.
4900 if (numtowrite) {
4901 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4902 "file %s\n", fsp_str_dbg(fsp)));
4903 close_status = close_file(req, fsp, NORMAL_CLOSE);
4906 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4907 fsp->fnum, (int)numtowrite, (int)nwritten,
4908 conn->num_files_open));
4910 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4911 reply_nterror(req, NT_STATUS_DISK_FULL);
4912 goto strict_unlock;
4915 if(!NT_STATUS_IS_OK(close_status)) {
4916 reply_nterror(req, close_status);
4917 goto strict_unlock;
4920 reply_outbuf(req, 1, 0);
4922 SSVAL(req->outbuf,smb_vwv0,nwritten);
4924 strict_unlock:
4925 if (numtowrite && !fsp->print_file) {
4926 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4929 END_PROFILE(SMBwriteclose);
4930 return;
4933 #undef DBGC_CLASS
4934 #define DBGC_CLASS DBGC_LOCKING
4936 /****************************************************************************
4937 Reply to a lock.
4938 ****************************************************************************/
4940 void reply_lock(struct smb_request *req)
4942 connection_struct *conn = req->conn;
4943 uint64_t count,offset;
4944 NTSTATUS status;
4945 files_struct *fsp;
4946 struct byte_range_lock *br_lck = NULL;
4948 START_PROFILE(SMBlock);
4950 if (req->wct < 5) {
4951 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4952 END_PROFILE(SMBlock);
4953 return;
4956 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4958 if (!check_fsp(conn, req, fsp)) {
4959 END_PROFILE(SMBlock);
4960 return;
4963 count = (uint64_t)IVAL(req->vwv+1, 0);
4964 offset = (uint64_t)IVAL(req->vwv+3, 0);
4966 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4967 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4969 br_lck = do_lock(req->sconn->msg_ctx,
4970 fsp,
4971 (uint64_t)req->smbpid,
4972 count,
4973 offset,
4974 WRITE_LOCK,
4975 WINDOWS_LOCK,
4976 False, /* Non-blocking lock. */
4977 &status,
4978 NULL,
4979 NULL);
4981 TALLOC_FREE(br_lck);
4983 if (NT_STATUS_V(status)) {
4984 reply_nterror(req, status);
4985 END_PROFILE(SMBlock);
4986 return;
4989 reply_outbuf(req, 0, 0);
4991 END_PROFILE(SMBlock);
4992 return;
4995 /****************************************************************************
4996 Reply to a unlock.
4997 ****************************************************************************/
4999 void reply_unlock(struct smb_request *req)
5001 connection_struct *conn = req->conn;
5002 uint64_t count,offset;
5003 NTSTATUS status;
5004 files_struct *fsp;
5006 START_PROFILE(SMBunlock);
5008 if (req->wct < 5) {
5009 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5010 END_PROFILE(SMBunlock);
5011 return;
5014 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5016 if (!check_fsp(conn, req, fsp)) {
5017 END_PROFILE(SMBunlock);
5018 return;
5021 count = (uint64_t)IVAL(req->vwv+1, 0);
5022 offset = (uint64_t)IVAL(req->vwv+3, 0);
5024 status = do_unlock(req->sconn->msg_ctx,
5025 fsp,
5026 (uint64_t)req->smbpid,
5027 count,
5028 offset,
5029 WINDOWS_LOCK);
5031 if (NT_STATUS_V(status)) {
5032 reply_nterror(req, status);
5033 END_PROFILE(SMBunlock);
5034 return;
5037 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5038 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5040 reply_outbuf(req, 0, 0);
5042 END_PROFILE(SMBunlock);
5043 return;
5046 #undef DBGC_CLASS
5047 #define DBGC_CLASS DBGC_ALL
5049 /****************************************************************************
5050 Reply to a tdis.
5051 conn POINTER CAN BE NULL HERE !
5052 ****************************************************************************/
5054 void reply_tdis(struct smb_request *req)
5056 connection_struct *conn = req->conn;
5057 START_PROFILE(SMBtdis);
5059 if (!conn) {
5060 DEBUG(4,("Invalid connection in tdis\n"));
5061 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5062 END_PROFILE(SMBtdis);
5063 return;
5066 conn->used = False;
5068 close_cnum(conn,req->vuid);
5069 req->conn = NULL;
5071 reply_outbuf(req, 0, 0);
5072 END_PROFILE(SMBtdis);
5073 return;
5076 /****************************************************************************
5077 Reply to a echo.
5078 conn POINTER CAN BE NULL HERE !
5079 ****************************************************************************/
5081 void reply_echo(struct smb_request *req)
5083 connection_struct *conn = req->conn;
5084 struct smb_perfcount_data local_pcd;
5085 struct smb_perfcount_data *cur_pcd;
5086 int smb_reverb;
5087 int seq_num;
5089 START_PROFILE(SMBecho);
5091 smb_init_perfcount_data(&local_pcd);
5093 if (req->wct < 1) {
5094 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5095 END_PROFILE(SMBecho);
5096 return;
5099 smb_reverb = SVAL(req->vwv+0, 0);
5101 reply_outbuf(req, 1, req->buflen);
5103 /* copy any incoming data back out */
5104 if (req->buflen > 0) {
5105 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5108 if (smb_reverb > 100) {
5109 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5110 smb_reverb = 100;
5113 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5115 /* this makes sure we catch the request pcd */
5116 if (seq_num == smb_reverb) {
5117 cur_pcd = &req->pcd;
5118 } else {
5119 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5120 cur_pcd = &local_pcd;
5123 SSVAL(req->outbuf,smb_vwv0,seq_num);
5125 show_msg((char *)req->outbuf);
5126 if (!srv_send_smb(req->sconn,
5127 (char *)req->outbuf,
5128 true, req->seqnum+1,
5129 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5130 cur_pcd))
5131 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5134 DEBUG(3,("echo %d times\n", smb_reverb));
5136 TALLOC_FREE(req->outbuf);
5138 END_PROFILE(SMBecho);
5139 return;
5142 /****************************************************************************
5143 Reply to a printopen.
5144 ****************************************************************************/
5146 void reply_printopen(struct smb_request *req)
5148 connection_struct *conn = req->conn;
5149 files_struct *fsp;
5150 NTSTATUS status;
5152 START_PROFILE(SMBsplopen);
5154 if (req->wct < 2) {
5155 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5156 END_PROFILE(SMBsplopen);
5157 return;
5160 if (!CAN_PRINT(conn)) {
5161 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5162 END_PROFILE(SMBsplopen);
5163 return;
5166 status = file_new(req, conn, &fsp);
5167 if(!NT_STATUS_IS_OK(status)) {
5168 reply_nterror(req, status);
5169 END_PROFILE(SMBsplopen);
5170 return;
5173 /* Open for exclusive use, write only. */
5174 status = print_spool_open(fsp, NULL, req->vuid);
5176 if (!NT_STATUS_IS_OK(status)) {
5177 file_free(req, fsp);
5178 reply_nterror(req, status);
5179 END_PROFILE(SMBsplopen);
5180 return;
5183 reply_outbuf(req, 1, 0);
5184 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5186 DEBUG(3,("openprint fd=%d fnum=%d\n",
5187 fsp->fh->fd, fsp->fnum));
5189 END_PROFILE(SMBsplopen);
5190 return;
5193 /****************************************************************************
5194 Reply to a printclose.
5195 ****************************************************************************/
5197 void reply_printclose(struct smb_request *req)
5199 connection_struct *conn = req->conn;
5200 files_struct *fsp;
5201 NTSTATUS status;
5203 START_PROFILE(SMBsplclose);
5205 if (req->wct < 1) {
5206 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5207 END_PROFILE(SMBsplclose);
5208 return;
5211 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5213 if (!check_fsp(conn, req, fsp)) {
5214 END_PROFILE(SMBsplclose);
5215 return;
5218 if (!CAN_PRINT(conn)) {
5219 reply_force_doserror(req, ERRSRV, ERRerror);
5220 END_PROFILE(SMBsplclose);
5221 return;
5224 DEBUG(3,("printclose fd=%d fnum=%d\n",
5225 fsp->fh->fd,fsp->fnum));
5227 status = close_file(req, fsp, NORMAL_CLOSE);
5229 if(!NT_STATUS_IS_OK(status)) {
5230 reply_nterror(req, status);
5231 END_PROFILE(SMBsplclose);
5232 return;
5235 reply_outbuf(req, 0, 0);
5237 END_PROFILE(SMBsplclose);
5238 return;
5241 /****************************************************************************
5242 Reply to a printqueue.
5243 ****************************************************************************/
5245 void reply_printqueue(struct smb_request *req)
5247 connection_struct *conn = req->conn;
5248 int max_count;
5249 int start_index;
5251 START_PROFILE(SMBsplretq);
5253 if (req->wct < 2) {
5254 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5255 END_PROFILE(SMBsplretq);
5256 return;
5259 max_count = SVAL(req->vwv+0, 0);
5260 start_index = SVAL(req->vwv+1, 0);
5262 /* we used to allow the client to get the cnum wrong, but that
5263 is really quite gross and only worked when there was only
5264 one printer - I think we should now only accept it if they
5265 get it right (tridge) */
5266 if (!CAN_PRINT(conn)) {
5267 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5268 END_PROFILE(SMBsplretq);
5269 return;
5272 reply_outbuf(req, 2, 3);
5273 SSVAL(req->outbuf,smb_vwv0,0);
5274 SSVAL(req->outbuf,smb_vwv1,0);
5275 SCVAL(smb_buf(req->outbuf),0,1);
5276 SSVAL(smb_buf(req->outbuf),1,0);
5278 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5279 start_index, max_count));
5282 TALLOC_CTX *mem_ctx = talloc_tos();
5283 NTSTATUS status;
5284 WERROR werr;
5285 const char *sharename = lp_servicename(SNUM(conn));
5286 struct rpc_pipe_client *cli = NULL;
5287 struct dcerpc_binding_handle *b = NULL;
5288 struct policy_handle handle;
5289 struct spoolss_DevmodeContainer devmode_ctr;
5290 union spoolss_JobInfo *info;
5291 uint32_t count;
5292 uint32_t num_to_get;
5293 uint32_t first;
5294 uint32_t i;
5296 ZERO_STRUCT(handle);
5298 status = rpc_pipe_open_interface(conn,
5299 &ndr_table_spoolss.syntax_id,
5300 conn->session_info,
5301 conn->sconn->remote_address,
5302 conn->sconn->msg_ctx,
5303 &cli);
5304 if (!NT_STATUS_IS_OK(status)) {
5305 DEBUG(0, ("reply_printqueue: "
5306 "could not connect to spoolss: %s\n",
5307 nt_errstr(status)));
5308 reply_nterror(req, status);
5309 goto out;
5311 b = cli->binding_handle;
5313 ZERO_STRUCT(devmode_ctr);
5315 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5316 sharename,
5317 NULL, devmode_ctr,
5318 SEC_FLAG_MAXIMUM_ALLOWED,
5319 &handle,
5320 &werr);
5321 if (!NT_STATUS_IS_OK(status)) {
5322 reply_nterror(req, status);
5323 goto out;
5325 if (!W_ERROR_IS_OK(werr)) {
5326 reply_nterror(req, werror_to_ntstatus(werr));
5327 goto out;
5330 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5331 &handle,
5332 0, /* firstjob */
5333 0xff, /* numjobs */
5334 2, /* level */
5335 0, /* offered */
5336 &count,
5337 &info);
5338 if (!W_ERROR_IS_OK(werr)) {
5339 reply_nterror(req, werror_to_ntstatus(werr));
5340 goto out;
5343 if (max_count > 0) {
5344 first = start_index;
5345 } else {
5346 first = start_index + max_count + 1;
5349 if (first >= count) {
5350 num_to_get = first;
5351 } else {
5352 num_to_get = first + MIN(ABS(max_count), count - first);
5355 for (i = first; i < num_to_get; i++) {
5356 char blob[28];
5357 char *p = blob;
5358 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5359 int qstatus;
5360 uint16_t qrapjobid = pjobid_to_rap(sharename,
5361 info[i].info2.job_id);
5363 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5364 qstatus = 2;
5365 } else {
5366 qstatus = 3;
5369 srv_put_dos_date2(p, 0, qtime);
5370 SCVAL(p, 4, qstatus);
5371 SSVAL(p, 5, qrapjobid);
5372 SIVAL(p, 7, info[i].info2.size);
5373 SCVAL(p, 11, 0);
5374 srvstr_push(blob, req->flags2, p+12,
5375 info[i].info2.notify_name, 16, STR_ASCII);
5377 if (message_push_blob(
5378 &req->outbuf,
5379 data_blob_const(
5380 blob, sizeof(blob))) == -1) {
5381 reply_nterror(req, NT_STATUS_NO_MEMORY);
5382 goto out;
5386 if (count > 0) {
5387 SSVAL(req->outbuf,smb_vwv0,count);
5388 SSVAL(req->outbuf,smb_vwv1,
5389 (max_count>0?first+count:first-1));
5390 SCVAL(smb_buf(req->outbuf),0,1);
5391 SSVAL(smb_buf(req->outbuf),1,28*count);
5395 DEBUG(3, ("%u entries returned in queue\n",
5396 (unsigned)count));
5398 out:
5399 if (b && is_valid_policy_hnd(&handle)) {
5400 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5405 END_PROFILE(SMBsplretq);
5406 return;
5409 /****************************************************************************
5410 Reply to a printwrite.
5411 ****************************************************************************/
5413 void reply_printwrite(struct smb_request *req)
5415 connection_struct *conn = req->conn;
5416 int numtowrite;
5417 const char *data;
5418 files_struct *fsp;
5420 START_PROFILE(SMBsplwr);
5422 if (req->wct < 1) {
5423 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5424 END_PROFILE(SMBsplwr);
5425 return;
5428 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5430 if (!check_fsp(conn, req, fsp)) {
5431 END_PROFILE(SMBsplwr);
5432 return;
5435 if (!fsp->print_file) {
5436 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5437 END_PROFILE(SMBsplwr);
5438 return;
5441 if (!CHECK_WRITE(fsp)) {
5442 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5443 END_PROFILE(SMBsplwr);
5444 return;
5447 numtowrite = SVAL(req->buf, 1);
5449 if (req->buflen < numtowrite + 3) {
5450 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5451 END_PROFILE(SMBsplwr);
5452 return;
5455 data = (const char *)req->buf + 3;
5457 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5458 reply_nterror(req, map_nt_error_from_unix(errno));
5459 END_PROFILE(SMBsplwr);
5460 return;
5463 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5465 END_PROFILE(SMBsplwr);
5466 return;
5469 /****************************************************************************
5470 Reply to a mkdir.
5471 ****************************************************************************/
5473 void reply_mkdir(struct smb_request *req)
5475 connection_struct *conn = req->conn;
5476 struct smb_filename *smb_dname = NULL;
5477 char *directory = NULL;
5478 NTSTATUS status;
5479 TALLOC_CTX *ctx = talloc_tos();
5481 START_PROFILE(SMBmkdir);
5483 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5484 STR_TERMINATE, &status);
5485 if (!NT_STATUS_IS_OK(status)) {
5486 reply_nterror(req, status);
5487 goto out;
5490 status = filename_convert(ctx, conn,
5491 req->flags2 & FLAGS2_DFS_PATHNAMES,
5492 directory,
5494 NULL,
5495 &smb_dname);
5496 if (!NT_STATUS_IS_OK(status)) {
5497 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5498 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5499 ERRSRV, ERRbadpath);
5500 goto out;
5502 reply_nterror(req, status);
5503 goto out;
5506 status = create_directory(conn, req, smb_dname);
5508 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5510 if (!NT_STATUS_IS_OK(status)) {
5512 if (!use_nt_status()
5513 && NT_STATUS_EQUAL(status,
5514 NT_STATUS_OBJECT_NAME_COLLISION)) {
5516 * Yes, in the DOS error code case we get a
5517 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5518 * samba4 torture test.
5520 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5523 reply_nterror(req, status);
5524 goto out;
5527 reply_outbuf(req, 0, 0);
5529 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5530 out:
5531 TALLOC_FREE(smb_dname);
5532 END_PROFILE(SMBmkdir);
5533 return;
5536 /****************************************************************************
5537 Reply to a rmdir.
5538 ****************************************************************************/
5540 void reply_rmdir(struct smb_request *req)
5542 connection_struct *conn = req->conn;
5543 struct smb_filename *smb_dname = NULL;
5544 char *directory = NULL;
5545 NTSTATUS status;
5546 TALLOC_CTX *ctx = talloc_tos();
5547 files_struct *fsp = NULL;
5548 int info = 0;
5549 struct smbd_server_connection *sconn = req->sconn;
5551 START_PROFILE(SMBrmdir);
5553 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5554 STR_TERMINATE, &status);
5555 if (!NT_STATUS_IS_OK(status)) {
5556 reply_nterror(req, status);
5557 goto out;
5560 status = filename_convert(ctx, conn,
5561 req->flags2 & FLAGS2_DFS_PATHNAMES,
5562 directory,
5564 NULL,
5565 &smb_dname);
5566 if (!NT_STATUS_IS_OK(status)) {
5567 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5568 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5569 ERRSRV, ERRbadpath);
5570 goto out;
5572 reply_nterror(req, status);
5573 goto out;
5576 if (is_ntfs_stream_smb_fname(smb_dname)) {
5577 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5578 goto out;
5581 status = SMB_VFS_CREATE_FILE(
5582 conn, /* conn */
5583 req, /* req */
5584 0, /* root_dir_fid */
5585 smb_dname, /* fname */
5586 DELETE_ACCESS, /* access_mask */
5587 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5588 FILE_SHARE_DELETE),
5589 FILE_OPEN, /* create_disposition*/
5590 FILE_DIRECTORY_FILE, /* create_options */
5591 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5592 0, /* oplock_request */
5593 0, /* allocation_size */
5594 0, /* private_flags */
5595 NULL, /* sd */
5596 NULL, /* ea_list */
5597 &fsp, /* result */
5598 &info); /* pinfo */
5600 if (!NT_STATUS_IS_OK(status)) {
5601 if (open_was_deferred(req->sconn, req->mid)) {
5602 /* We have re-scheduled this call. */
5603 goto out;
5605 reply_nterror(req, status);
5606 goto out;
5609 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5610 if (!NT_STATUS_IS_OK(status)) {
5611 close_file(req, fsp, ERROR_CLOSE);
5612 reply_nterror(req, status);
5613 goto out;
5616 if (!set_delete_on_close(fsp, true,
5617 conn->session_info->security_token,
5618 conn->session_info->unix_token)) {
5619 close_file(req, fsp, ERROR_CLOSE);
5620 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5621 goto out;
5624 status = close_file(req, fsp, NORMAL_CLOSE);
5625 if (!NT_STATUS_IS_OK(status)) {
5626 reply_nterror(req, status);
5627 } else {
5628 reply_outbuf(req, 0, 0);
5631 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5633 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5634 out:
5635 TALLOC_FREE(smb_dname);
5636 END_PROFILE(SMBrmdir);
5637 return;
5640 /*******************************************************************
5641 Resolve wildcards in a filename rename.
5642 ********************************************************************/
5644 static bool resolve_wildcards(TALLOC_CTX *ctx,
5645 const char *name1,
5646 const char *name2,
5647 char **pp_newname)
5649 char *name2_copy = NULL;
5650 char *root1 = NULL;
5651 char *root2 = NULL;
5652 char *ext1 = NULL;
5653 char *ext2 = NULL;
5654 char *p,*p2, *pname1, *pname2;
5656 name2_copy = talloc_strdup(ctx, name2);
5657 if (!name2_copy) {
5658 return False;
5661 pname1 = strrchr_m(name1,'/');
5662 pname2 = strrchr_m(name2_copy,'/');
5664 if (!pname1 || !pname2) {
5665 return False;
5668 /* Truncate the copy of name2 at the last '/' */
5669 *pname2 = '\0';
5671 /* Now go past the '/' */
5672 pname1++;
5673 pname2++;
5675 root1 = talloc_strdup(ctx, pname1);
5676 root2 = talloc_strdup(ctx, pname2);
5678 if (!root1 || !root2) {
5679 return False;
5682 p = strrchr_m(root1,'.');
5683 if (p) {
5684 *p = 0;
5685 ext1 = talloc_strdup(ctx, p+1);
5686 } else {
5687 ext1 = talloc_strdup(ctx, "");
5689 p = strrchr_m(root2,'.');
5690 if (p) {
5691 *p = 0;
5692 ext2 = talloc_strdup(ctx, p+1);
5693 } else {
5694 ext2 = talloc_strdup(ctx, "");
5697 if (!ext1 || !ext2) {
5698 return False;
5701 p = root1;
5702 p2 = root2;
5703 while (*p2) {
5704 if (*p2 == '?') {
5705 /* Hmmm. Should this be mb-aware ? */
5706 *p2 = *p;
5707 p2++;
5708 } else if (*p2 == '*') {
5709 *p2 = '\0';
5710 root2 = talloc_asprintf(ctx, "%s%s",
5711 root2,
5713 if (!root2) {
5714 return False;
5716 break;
5717 } else {
5718 p2++;
5720 if (*p) {
5721 p++;
5725 p = ext1;
5726 p2 = ext2;
5727 while (*p2) {
5728 if (*p2 == '?') {
5729 /* Hmmm. Should this be mb-aware ? */
5730 *p2 = *p;
5731 p2++;
5732 } else if (*p2 == '*') {
5733 *p2 = '\0';
5734 ext2 = talloc_asprintf(ctx, "%s%s",
5735 ext2,
5737 if (!ext2) {
5738 return False;
5740 break;
5741 } else {
5742 p2++;
5744 if (*p) {
5745 p++;
5749 if (*ext2) {
5750 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5751 name2_copy,
5752 root2,
5753 ext2);
5754 } else {
5755 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5756 name2_copy,
5757 root2);
5760 if (!*pp_newname) {
5761 return False;
5764 return True;
5767 /****************************************************************************
5768 Ensure open files have their names updated. Updated to notify other smbd's
5769 asynchronously.
5770 ****************************************************************************/
5772 static void rename_open_files(connection_struct *conn,
5773 struct share_mode_lock *lck,
5774 uint32_t orig_name_hash,
5775 const struct smb_filename *smb_fname_dst)
5777 files_struct *fsp;
5778 bool did_rename = False;
5779 NTSTATUS status;
5780 uint32_t new_name_hash = 0;
5782 for(fsp = file_find_di_first(conn->sconn, lck->data->id); fsp;
5783 fsp = file_find_di_next(fsp)) {
5784 /* fsp_name is a relative path under the fsp. To change this for other
5785 sharepaths we need to manipulate relative paths. */
5786 /* TODO - create the absolute path and manipulate the newname
5787 relative to the sharepath. */
5788 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5789 continue;
5791 if (fsp->name_hash != orig_name_hash) {
5792 continue;
5794 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5795 "(file_id %s) from %s -> %s\n", fsp->fnum,
5796 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5797 smb_fname_str_dbg(smb_fname_dst)));
5799 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5800 if (NT_STATUS_IS_OK(status)) {
5801 did_rename = True;
5802 new_name_hash = fsp->name_hash;
5806 if (!did_rename) {
5807 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5808 "for %s\n", file_id_string_tos(&lck->data->id),
5809 smb_fname_str_dbg(smb_fname_dst)));
5812 /* Send messages to all smbd's (not ourself) that the name has changed. */
5813 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5814 orig_name_hash, new_name_hash,
5815 smb_fname_dst);
5819 /****************************************************************************
5820 We need to check if the source path is a parent directory of the destination
5821 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5822 refuse the rename with a sharing violation. Under UNIX the above call can
5823 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5824 probably need to check that the client is a Windows one before disallowing
5825 this as a UNIX client (one with UNIX extensions) can know the source is a
5826 symlink and make this decision intelligently. Found by an excellent bug
5827 report from <AndyLiebman@aol.com>.
5828 ****************************************************************************/
5830 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5831 const struct smb_filename *smb_fname_dst)
5833 const char *psrc = smb_fname_src->base_name;
5834 const char *pdst = smb_fname_dst->base_name;
5835 size_t slen;
5837 if (psrc[0] == '.' && psrc[1] == '/') {
5838 psrc += 2;
5840 if (pdst[0] == '.' && pdst[1] == '/') {
5841 pdst += 2;
5843 if ((slen = strlen(psrc)) > strlen(pdst)) {
5844 return False;
5846 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5850 * Do the notify calls from a rename
5853 static void notify_rename(connection_struct *conn, bool is_dir,
5854 const struct smb_filename *smb_fname_src,
5855 const struct smb_filename *smb_fname_dst)
5857 char *parent_dir_src = NULL;
5858 char *parent_dir_dst = NULL;
5859 uint32 mask;
5861 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5862 : FILE_NOTIFY_CHANGE_FILE_NAME;
5864 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5865 &parent_dir_src, NULL) ||
5866 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5867 &parent_dir_dst, NULL)) {
5868 goto out;
5871 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5872 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5873 smb_fname_src->base_name);
5874 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5875 smb_fname_dst->base_name);
5877 else {
5878 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5879 smb_fname_src->base_name);
5880 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5881 smb_fname_dst->base_name);
5884 /* this is a strange one. w2k3 gives an additional event for
5885 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5886 files, but not directories */
5887 if (!is_dir) {
5888 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5889 FILE_NOTIFY_CHANGE_ATTRIBUTES
5890 |FILE_NOTIFY_CHANGE_CREATION,
5891 smb_fname_dst->base_name);
5893 out:
5894 TALLOC_FREE(parent_dir_src);
5895 TALLOC_FREE(parent_dir_dst);
5898 /****************************************************************************
5899 Returns an error if the parent directory for a filename is open in an
5900 incompatible way.
5901 ****************************************************************************/
5903 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
5904 const struct smb_filename *smb_fname_dst_in)
5906 char *parent_dir = NULL;
5907 struct smb_filename smb_fname_parent;
5908 struct file_id id;
5909 files_struct *fsp = NULL;
5910 int ret;
5912 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
5913 &parent_dir, NULL)) {
5914 return NT_STATUS_NO_MEMORY;
5916 ZERO_STRUCT(smb_fname_parent);
5917 smb_fname_parent.base_name = parent_dir;
5919 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
5920 if (ret == -1) {
5921 return map_nt_error_from_unix(errno);
5925 * We're only checking on this smbd here, mostly good
5926 * enough.. and will pass tests.
5929 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
5930 for (fsp = file_find_di_first(conn->sconn, id); fsp;
5931 fsp = file_find_di_next(fsp)) {
5932 if (fsp->access_mask & DELETE_ACCESS) {
5933 return NT_STATUS_SHARING_VIOLATION;
5936 return NT_STATUS_OK;
5939 /****************************************************************************
5940 Rename an open file - given an fsp.
5941 ****************************************************************************/
5943 NTSTATUS rename_internals_fsp(connection_struct *conn,
5944 files_struct *fsp,
5945 const struct smb_filename *smb_fname_dst_in,
5946 uint32 attrs,
5947 bool replace_if_exists)
5949 TALLOC_CTX *ctx = talloc_tos();
5950 struct smb_filename *smb_fname_dst = NULL;
5951 NTSTATUS status = NT_STATUS_OK;
5952 struct share_mode_lock *lck = NULL;
5953 bool dst_exists, old_is_stream, new_is_stream;
5955 status = check_name(conn, smb_fname_dst_in->base_name);
5956 if (!NT_STATUS_IS_OK(status)) {
5957 return status;
5960 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
5961 if (!NT_STATUS_IS_OK(status)) {
5962 return status;
5965 /* Make a copy of the dst smb_fname structs */
5967 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5968 if (!NT_STATUS_IS_OK(status)) {
5969 goto out;
5973 * Check for special case with case preserving and not
5974 * case sensitive. If the old last component differs from the original
5975 * last component only by case, then we should allow
5976 * the rename (user is trying to change the case of the
5977 * filename).
5979 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5980 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5981 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5982 char *last_slash;
5983 char *fname_dst_lcomp_base_mod = NULL;
5984 struct smb_filename *smb_fname_orig_lcomp = NULL;
5987 * Get the last component of the destination name.
5989 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5990 if (last_slash) {
5991 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5992 } else {
5993 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
5995 if (!fname_dst_lcomp_base_mod) {
5996 status = NT_STATUS_NO_MEMORY;
5997 goto out;
6001 * Create an smb_filename struct using the original last
6002 * component of the destination.
6004 status = create_synthetic_smb_fname_split(ctx,
6005 smb_fname_dst->original_lcomp, NULL,
6006 &smb_fname_orig_lcomp);
6007 if (!NT_STATUS_IS_OK(status)) {
6008 TALLOC_FREE(fname_dst_lcomp_base_mod);
6009 goto out;
6012 /* If the base names only differ by case, use original. */
6013 if(!strcsequal(fname_dst_lcomp_base_mod,
6014 smb_fname_orig_lcomp->base_name)) {
6015 char *tmp;
6017 * Replace the modified last component with the
6018 * original.
6020 if (last_slash) {
6021 *last_slash = '\0'; /* Truncate at the '/' */
6022 tmp = talloc_asprintf(smb_fname_dst,
6023 "%s/%s",
6024 smb_fname_dst->base_name,
6025 smb_fname_orig_lcomp->base_name);
6026 } else {
6027 tmp = talloc_asprintf(smb_fname_dst,
6028 "%s",
6029 smb_fname_orig_lcomp->base_name);
6031 if (tmp == NULL) {
6032 status = NT_STATUS_NO_MEMORY;
6033 TALLOC_FREE(fname_dst_lcomp_base_mod);
6034 TALLOC_FREE(smb_fname_orig_lcomp);
6035 goto out;
6037 TALLOC_FREE(smb_fname_dst->base_name);
6038 smb_fname_dst->base_name = tmp;
6041 /* If the stream_names only differ by case, use original. */
6042 if(!strcsequal(smb_fname_dst->stream_name,
6043 smb_fname_orig_lcomp->stream_name)) {
6044 char *tmp = NULL;
6045 /* Use the original stream. */
6046 tmp = talloc_strdup(smb_fname_dst,
6047 smb_fname_orig_lcomp->stream_name);
6048 if (tmp == NULL) {
6049 status = NT_STATUS_NO_MEMORY;
6050 TALLOC_FREE(fname_dst_lcomp_base_mod);
6051 TALLOC_FREE(smb_fname_orig_lcomp);
6052 goto out;
6054 TALLOC_FREE(smb_fname_dst->stream_name);
6055 smb_fname_dst->stream_name = tmp;
6057 TALLOC_FREE(fname_dst_lcomp_base_mod);
6058 TALLOC_FREE(smb_fname_orig_lcomp);
6062 * If the src and dest names are identical - including case,
6063 * don't do the rename, just return success.
6066 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6067 strcsequal(fsp->fsp_name->stream_name,
6068 smb_fname_dst->stream_name)) {
6069 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6070 "- returning success\n",
6071 smb_fname_str_dbg(smb_fname_dst)));
6072 status = NT_STATUS_OK;
6073 goto out;
6076 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6077 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6079 /* Return the correct error code if both names aren't streams. */
6080 if (!old_is_stream && new_is_stream) {
6081 status = NT_STATUS_OBJECT_NAME_INVALID;
6082 goto out;
6085 if (old_is_stream && !new_is_stream) {
6086 status = NT_STATUS_INVALID_PARAMETER;
6087 goto out;
6090 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6092 if(!replace_if_exists && dst_exists) {
6093 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6094 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6095 smb_fname_str_dbg(smb_fname_dst)));
6096 status = NT_STATUS_OBJECT_NAME_COLLISION;
6097 goto out;
6100 if (dst_exists) {
6101 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6102 &smb_fname_dst->st);
6103 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6104 fileid);
6105 /* The file can be open when renaming a stream */
6106 if (dst_fsp && !new_is_stream) {
6107 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6108 status = NT_STATUS_ACCESS_DENIED;
6109 goto out;
6113 /* Ensure we have a valid stat struct for the source. */
6114 status = vfs_stat_fsp(fsp);
6115 if (!NT_STATUS_IS_OK(status)) {
6116 goto out;
6119 status = can_rename(conn, fsp, attrs);
6121 if (!NT_STATUS_IS_OK(status)) {
6122 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6123 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6124 smb_fname_str_dbg(smb_fname_dst)));
6125 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6126 status = NT_STATUS_ACCESS_DENIED;
6127 goto out;
6130 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6131 status = NT_STATUS_ACCESS_DENIED;
6134 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6137 * We have the file open ourselves, so not being able to get the
6138 * corresponding share mode lock is a fatal error.
6141 SMB_ASSERT(lck != NULL);
6143 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6144 uint32 create_options = fsp->fh->private_options;
6146 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6147 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6148 smb_fname_str_dbg(smb_fname_dst)));
6150 if (!lp_posix_pathnames() &&
6151 (lp_map_archive(SNUM(conn)) ||
6152 lp_store_dos_attributes(SNUM(conn)))) {
6153 /* We must set the archive bit on the newly
6154 renamed file. */
6155 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6156 uint32_t old_dosmode = dos_mode(conn,
6157 smb_fname_dst);
6158 file_set_dosmode(conn,
6159 smb_fname_dst,
6160 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6161 NULL,
6162 true);
6166 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6167 smb_fname_dst);
6169 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6172 * A rename acts as a new file create w.r.t. allowing an initial delete
6173 * on close, probably because in Windows there is a new handle to the
6174 * new file. If initial delete on close was requested but not
6175 * originally set, we need to set it here. This is probably not 100% correct,
6176 * but will work for the CIFSFS client which in non-posix mode
6177 * depends on these semantics. JRA.
6180 if (create_options & FILE_DELETE_ON_CLOSE) {
6181 status = can_set_delete_on_close(fsp, 0);
6183 if (NT_STATUS_IS_OK(status)) {
6184 /* Note that here we set the *inital* delete on close flag,
6185 * not the regular one. The magic gets handled in close. */
6186 fsp->initial_delete_on_close = True;
6189 TALLOC_FREE(lck);
6190 status = NT_STATUS_OK;
6191 goto out;
6194 TALLOC_FREE(lck);
6196 if (errno == ENOTDIR || errno == EISDIR) {
6197 status = NT_STATUS_OBJECT_NAME_COLLISION;
6198 } else {
6199 status = map_nt_error_from_unix(errno);
6202 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6203 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6204 smb_fname_str_dbg(smb_fname_dst)));
6206 out:
6207 TALLOC_FREE(smb_fname_dst);
6209 return status;
6212 /****************************************************************************
6213 The guts of the rename command, split out so it may be called by the NT SMB
6214 code.
6215 ****************************************************************************/
6217 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6218 connection_struct *conn,
6219 struct smb_request *req,
6220 struct smb_filename *smb_fname_src,
6221 struct smb_filename *smb_fname_dst,
6222 uint32 attrs,
6223 bool replace_if_exists,
6224 bool src_has_wild,
6225 bool dest_has_wild,
6226 uint32_t access_mask)
6228 char *fname_src_dir = NULL;
6229 char *fname_src_mask = NULL;
6230 int count=0;
6231 NTSTATUS status = NT_STATUS_OK;
6232 struct smb_Dir *dir_hnd = NULL;
6233 const char *dname = NULL;
6234 char *talloced = NULL;
6235 long offset = 0;
6236 int create_options = 0;
6237 bool posix_pathnames = lp_posix_pathnames();
6240 * Split the old name into directory and last component
6241 * strings. Note that unix_convert may have stripped off a
6242 * leading ./ from both name and newname if the rename is
6243 * at the root of the share. We need to make sure either both
6244 * name and newname contain a / character or neither of them do
6245 * as this is checked in resolve_wildcards().
6248 /* Split up the directory from the filename/mask. */
6249 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6250 &fname_src_dir, &fname_src_mask);
6251 if (!NT_STATUS_IS_OK(status)) {
6252 status = NT_STATUS_NO_MEMORY;
6253 goto out;
6257 * We should only check the mangled cache
6258 * here if unix_convert failed. This means
6259 * that the path in 'mask' doesn't exist
6260 * on the file system and so we need to look
6261 * for a possible mangle. This patch from
6262 * Tine Smukavec <valentin.smukavec@hermes.si>.
6265 if (!VALID_STAT(smb_fname_src->st) &&
6266 mangle_is_mangled(fname_src_mask, conn->params)) {
6267 char *new_mask = NULL;
6268 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6269 conn->params);
6270 if (new_mask) {
6271 TALLOC_FREE(fname_src_mask);
6272 fname_src_mask = new_mask;
6276 if (!src_has_wild) {
6277 files_struct *fsp;
6280 * Only one file needs to be renamed. Append the mask back
6281 * onto the directory.
6283 TALLOC_FREE(smb_fname_src->base_name);
6284 if (ISDOT(fname_src_dir)) {
6285 /* Ensure we use canonical names on open. */
6286 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6287 "%s",
6288 fname_src_mask);
6289 } else {
6290 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6291 "%s/%s",
6292 fname_src_dir,
6293 fname_src_mask);
6295 if (!smb_fname_src->base_name) {
6296 status = NT_STATUS_NO_MEMORY;
6297 goto out;
6300 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6301 "case_preserve = %d, short case preserve = %d, "
6302 "directory = %s, newname = %s, "
6303 "last_component_dest = %s\n",
6304 conn->case_sensitive, conn->case_preserve,
6305 conn->short_case_preserve,
6306 smb_fname_str_dbg(smb_fname_src),
6307 smb_fname_str_dbg(smb_fname_dst),
6308 smb_fname_dst->original_lcomp));
6310 /* The dest name still may have wildcards. */
6311 if (dest_has_wild) {
6312 char *fname_dst_mod = NULL;
6313 if (!resolve_wildcards(smb_fname_dst,
6314 smb_fname_src->base_name,
6315 smb_fname_dst->base_name,
6316 &fname_dst_mod)) {
6317 DEBUG(6, ("rename_internals: resolve_wildcards "
6318 "%s %s failed\n",
6319 smb_fname_src->base_name,
6320 smb_fname_dst->base_name));
6321 status = NT_STATUS_NO_MEMORY;
6322 goto out;
6324 TALLOC_FREE(smb_fname_dst->base_name);
6325 smb_fname_dst->base_name = fname_dst_mod;
6328 ZERO_STRUCT(smb_fname_src->st);
6329 if (posix_pathnames) {
6330 SMB_VFS_LSTAT(conn, smb_fname_src);
6331 } else {
6332 SMB_VFS_STAT(conn, smb_fname_src);
6335 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6336 create_options |= FILE_DIRECTORY_FILE;
6339 status = SMB_VFS_CREATE_FILE(
6340 conn, /* conn */
6341 req, /* req */
6342 0, /* root_dir_fid */
6343 smb_fname_src, /* fname */
6344 access_mask, /* access_mask */
6345 (FILE_SHARE_READ | /* share_access */
6346 FILE_SHARE_WRITE),
6347 FILE_OPEN, /* create_disposition*/
6348 create_options, /* create_options */
6349 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6350 0, /* oplock_request */
6351 0, /* allocation_size */
6352 0, /* private_flags */
6353 NULL, /* sd */
6354 NULL, /* ea_list */
6355 &fsp, /* result */
6356 NULL); /* pinfo */
6358 if (!NT_STATUS_IS_OK(status)) {
6359 DEBUG(3, ("Could not open rename source %s: %s\n",
6360 smb_fname_str_dbg(smb_fname_src),
6361 nt_errstr(status)));
6362 goto out;
6365 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6366 attrs, replace_if_exists);
6368 close_file(req, fsp, NORMAL_CLOSE);
6370 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6371 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6372 smb_fname_str_dbg(smb_fname_dst)));
6374 goto out;
6378 * Wildcards - process each file that matches.
6380 if (strequal(fname_src_mask, "????????.???")) {
6381 TALLOC_FREE(fname_src_mask);
6382 fname_src_mask = talloc_strdup(ctx, "*");
6383 if (!fname_src_mask) {
6384 status = NT_STATUS_NO_MEMORY;
6385 goto out;
6389 status = check_name(conn, fname_src_dir);
6390 if (!NT_STATUS_IS_OK(status)) {
6391 goto out;
6394 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6395 attrs);
6396 if (dir_hnd == NULL) {
6397 status = map_nt_error_from_unix(errno);
6398 goto out;
6401 status = NT_STATUS_NO_SUCH_FILE;
6403 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6404 * - gentest fix. JRA
6407 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6408 &talloced))) {
6409 files_struct *fsp = NULL;
6410 char *destname = NULL;
6411 bool sysdir_entry = False;
6413 /* Quick check for "." and ".." */
6414 if (ISDOT(dname) || ISDOTDOT(dname)) {
6415 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6416 sysdir_entry = True;
6417 } else {
6418 TALLOC_FREE(talloced);
6419 continue;
6423 if (!is_visible_file(conn, fname_src_dir, dname,
6424 &smb_fname_src->st, false)) {
6425 TALLOC_FREE(talloced);
6426 continue;
6429 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6430 TALLOC_FREE(talloced);
6431 continue;
6434 if (sysdir_entry) {
6435 status = NT_STATUS_OBJECT_NAME_INVALID;
6436 break;
6439 TALLOC_FREE(smb_fname_src->base_name);
6440 if (ISDOT(fname_src_dir)) {
6441 /* Ensure we use canonical names on open. */
6442 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6443 "%s",
6444 dname);
6445 } else {
6446 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6447 "%s/%s",
6448 fname_src_dir,
6449 dname);
6451 if (!smb_fname_src->base_name) {
6452 status = NT_STATUS_NO_MEMORY;
6453 goto out;
6456 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6457 smb_fname_dst->base_name,
6458 &destname)) {
6459 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6460 smb_fname_src->base_name, destname));
6461 TALLOC_FREE(talloced);
6462 continue;
6464 if (!destname) {
6465 status = NT_STATUS_NO_MEMORY;
6466 goto out;
6469 TALLOC_FREE(smb_fname_dst->base_name);
6470 smb_fname_dst->base_name = destname;
6472 ZERO_STRUCT(smb_fname_src->st);
6473 if (posix_pathnames) {
6474 SMB_VFS_LSTAT(conn, smb_fname_src);
6475 } else {
6476 SMB_VFS_STAT(conn, smb_fname_src);
6479 create_options = 0;
6481 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6482 create_options |= FILE_DIRECTORY_FILE;
6485 status = SMB_VFS_CREATE_FILE(
6486 conn, /* conn */
6487 req, /* req */
6488 0, /* root_dir_fid */
6489 smb_fname_src, /* fname */
6490 access_mask, /* access_mask */
6491 (FILE_SHARE_READ | /* share_access */
6492 FILE_SHARE_WRITE),
6493 FILE_OPEN, /* create_disposition*/
6494 create_options, /* create_options */
6495 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6496 0, /* oplock_request */
6497 0, /* allocation_size */
6498 0, /* private_flags */
6499 NULL, /* sd */
6500 NULL, /* ea_list */
6501 &fsp, /* result */
6502 NULL); /* pinfo */
6504 if (!NT_STATUS_IS_OK(status)) {
6505 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6506 "returned %s rename %s -> %s\n",
6507 nt_errstr(status),
6508 smb_fname_str_dbg(smb_fname_src),
6509 smb_fname_str_dbg(smb_fname_dst)));
6510 break;
6513 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6514 dname);
6515 if (!smb_fname_dst->original_lcomp) {
6516 status = NT_STATUS_NO_MEMORY;
6517 goto out;
6520 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6521 attrs, replace_if_exists);
6523 close_file(req, fsp, NORMAL_CLOSE);
6525 if (!NT_STATUS_IS_OK(status)) {
6526 DEBUG(3, ("rename_internals_fsp returned %s for "
6527 "rename %s -> %s\n", nt_errstr(status),
6528 smb_fname_str_dbg(smb_fname_src),
6529 smb_fname_str_dbg(smb_fname_dst)));
6530 break;
6533 count++;
6535 DEBUG(3,("rename_internals: doing rename on %s -> "
6536 "%s\n", smb_fname_str_dbg(smb_fname_src),
6537 smb_fname_str_dbg(smb_fname_src)));
6538 TALLOC_FREE(talloced);
6540 TALLOC_FREE(dir_hnd);
6542 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6543 status = map_nt_error_from_unix(errno);
6546 out:
6547 TALLOC_FREE(talloced);
6548 TALLOC_FREE(fname_src_dir);
6549 TALLOC_FREE(fname_src_mask);
6550 return status;
6553 /****************************************************************************
6554 Reply to a mv.
6555 ****************************************************************************/
6557 void reply_mv(struct smb_request *req)
6559 connection_struct *conn = req->conn;
6560 char *name = NULL;
6561 char *newname = NULL;
6562 const char *p;
6563 uint32 attrs;
6564 NTSTATUS status;
6565 bool src_has_wcard = False;
6566 bool dest_has_wcard = False;
6567 TALLOC_CTX *ctx = talloc_tos();
6568 struct smb_filename *smb_fname_src = NULL;
6569 struct smb_filename *smb_fname_dst = NULL;
6570 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6571 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6572 bool stream_rename = false;
6574 START_PROFILE(SMBmv);
6576 if (req->wct < 1) {
6577 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6578 goto out;
6581 attrs = SVAL(req->vwv+0, 0);
6583 p = (const char *)req->buf + 1;
6584 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6585 &status, &src_has_wcard);
6586 if (!NT_STATUS_IS_OK(status)) {
6587 reply_nterror(req, status);
6588 goto out;
6590 p++;
6591 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6592 &status, &dest_has_wcard);
6593 if (!NT_STATUS_IS_OK(status)) {
6594 reply_nterror(req, status);
6595 goto out;
6598 if (!lp_posix_pathnames()) {
6599 /* The newname must begin with a ':' if the
6600 name contains a ':'. */
6601 if (strchr_m(name, ':')) {
6602 if (newname[0] != ':') {
6603 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6604 goto out;
6606 stream_rename = true;
6610 status = filename_convert(ctx,
6611 conn,
6612 req->flags2 & FLAGS2_DFS_PATHNAMES,
6613 name,
6614 src_ucf_flags,
6615 &src_has_wcard,
6616 &smb_fname_src);
6618 if (!NT_STATUS_IS_OK(status)) {
6619 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6620 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6621 ERRSRV, ERRbadpath);
6622 goto out;
6624 reply_nterror(req, status);
6625 goto out;
6628 status = filename_convert(ctx,
6629 conn,
6630 req->flags2 & FLAGS2_DFS_PATHNAMES,
6631 newname,
6632 dst_ucf_flags,
6633 &dest_has_wcard,
6634 &smb_fname_dst);
6636 if (!NT_STATUS_IS_OK(status)) {
6637 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6638 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6639 ERRSRV, ERRbadpath);
6640 goto out;
6642 reply_nterror(req, status);
6643 goto out;
6646 if (stream_rename) {
6647 /* smb_fname_dst->base_name must be the same as
6648 smb_fname_src->base_name. */
6649 TALLOC_FREE(smb_fname_dst->base_name);
6650 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6651 smb_fname_src->base_name);
6652 if (!smb_fname_dst->base_name) {
6653 reply_nterror(req, NT_STATUS_NO_MEMORY);
6654 goto out;
6658 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6659 smb_fname_str_dbg(smb_fname_dst)));
6661 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6662 attrs, False, src_has_wcard, dest_has_wcard,
6663 DELETE_ACCESS);
6664 if (!NT_STATUS_IS_OK(status)) {
6665 if (open_was_deferred(req->sconn, req->mid)) {
6666 /* We have re-scheduled this call. */
6667 goto out;
6669 reply_nterror(req, status);
6670 goto out;
6673 reply_outbuf(req, 0, 0);
6674 out:
6675 TALLOC_FREE(smb_fname_src);
6676 TALLOC_FREE(smb_fname_dst);
6677 END_PROFILE(SMBmv);
6678 return;
6681 /*******************************************************************
6682 Copy a file as part of a reply_copy.
6683 ******************************************************************/
6686 * TODO: check error codes on all callers
6689 NTSTATUS copy_file(TALLOC_CTX *ctx,
6690 connection_struct *conn,
6691 struct smb_filename *smb_fname_src,
6692 struct smb_filename *smb_fname_dst,
6693 int ofun,
6694 int count,
6695 bool target_is_directory)
6697 struct smb_filename *smb_fname_dst_tmp = NULL;
6698 off_t ret=-1;
6699 files_struct *fsp1,*fsp2;
6700 uint32 dosattrs;
6701 uint32 new_create_disposition;
6702 NTSTATUS status;
6705 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6706 if (!NT_STATUS_IS_OK(status)) {
6707 return status;
6711 * If the target is a directory, extract the last component from the
6712 * src filename and append it to the dst filename
6714 if (target_is_directory) {
6715 const char *p;
6717 /* dest/target can't be a stream if it's a directory. */
6718 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6720 p = strrchr_m(smb_fname_src->base_name,'/');
6721 if (p) {
6722 p++;
6723 } else {
6724 p = smb_fname_src->base_name;
6726 smb_fname_dst_tmp->base_name =
6727 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6729 if (!smb_fname_dst_tmp->base_name) {
6730 status = NT_STATUS_NO_MEMORY;
6731 goto out;
6735 status = vfs_file_exist(conn, smb_fname_src);
6736 if (!NT_STATUS_IS_OK(status)) {
6737 goto out;
6740 if (!target_is_directory && count) {
6741 new_create_disposition = FILE_OPEN;
6742 } else {
6743 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6744 0, ofun,
6745 NULL, NULL,
6746 &new_create_disposition,
6747 NULL,
6748 NULL)) {
6749 status = NT_STATUS_INVALID_PARAMETER;
6750 goto out;
6754 /* Open the src file for reading. */
6755 status = SMB_VFS_CREATE_FILE(
6756 conn, /* conn */
6757 NULL, /* req */
6758 0, /* root_dir_fid */
6759 smb_fname_src, /* fname */
6760 FILE_GENERIC_READ, /* access_mask */
6761 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6762 FILE_OPEN, /* create_disposition*/
6763 0, /* create_options */
6764 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6765 INTERNAL_OPEN_ONLY, /* oplock_request */
6766 0, /* allocation_size */
6767 0, /* private_flags */
6768 NULL, /* sd */
6769 NULL, /* ea_list */
6770 &fsp1, /* result */
6771 NULL); /* psbuf */
6773 if (!NT_STATUS_IS_OK(status)) {
6774 goto out;
6777 dosattrs = dos_mode(conn, smb_fname_src);
6779 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6780 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6783 /* Open the dst file for writing. */
6784 status = SMB_VFS_CREATE_FILE(
6785 conn, /* conn */
6786 NULL, /* req */
6787 0, /* root_dir_fid */
6788 smb_fname_dst, /* fname */
6789 FILE_GENERIC_WRITE, /* access_mask */
6790 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6791 new_create_disposition, /* create_disposition*/
6792 0, /* create_options */
6793 dosattrs, /* file_attributes */
6794 INTERNAL_OPEN_ONLY, /* oplock_request */
6795 0, /* allocation_size */
6796 0, /* private_flags */
6797 NULL, /* sd */
6798 NULL, /* ea_list */
6799 &fsp2, /* result */
6800 NULL); /* psbuf */
6802 if (!NT_STATUS_IS_OK(status)) {
6803 close_file(NULL, fsp1, ERROR_CLOSE);
6804 goto out;
6807 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6808 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6809 if (ret == -1) {
6810 DEBUG(0, ("error - vfs lseek returned error %s\n",
6811 strerror(errno)));
6812 status = map_nt_error_from_unix(errno);
6813 close_file(NULL, fsp1, ERROR_CLOSE);
6814 close_file(NULL, fsp2, ERROR_CLOSE);
6815 goto out;
6819 /* Do the actual copy. */
6820 if (smb_fname_src->st.st_ex_size) {
6821 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6822 } else {
6823 ret = 0;
6826 close_file(NULL, fsp1, NORMAL_CLOSE);
6828 /* Ensure the modtime is set correctly on the destination file. */
6829 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6832 * As we are opening fsp1 read-only we only expect
6833 * an error on close on fsp2 if we are out of space.
6834 * Thus we don't look at the error return from the
6835 * close of fsp1.
6837 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6839 if (!NT_STATUS_IS_OK(status)) {
6840 goto out;
6843 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
6844 status = NT_STATUS_DISK_FULL;
6845 goto out;
6848 status = NT_STATUS_OK;
6850 out:
6851 TALLOC_FREE(smb_fname_dst_tmp);
6852 return status;
6855 /****************************************************************************
6856 Reply to a file copy.
6857 ****************************************************************************/
6859 void reply_copy(struct smb_request *req)
6861 connection_struct *conn = req->conn;
6862 struct smb_filename *smb_fname_src = NULL;
6863 struct smb_filename *smb_fname_dst = NULL;
6864 char *fname_src = NULL;
6865 char *fname_dst = NULL;
6866 char *fname_src_mask = NULL;
6867 char *fname_src_dir = NULL;
6868 const char *p;
6869 int count=0;
6870 int error = ERRnoaccess;
6871 int tid2;
6872 int ofun;
6873 int flags;
6874 bool target_is_directory=False;
6875 bool source_has_wild = False;
6876 bool dest_has_wild = False;
6877 NTSTATUS status;
6878 TALLOC_CTX *ctx = talloc_tos();
6880 START_PROFILE(SMBcopy);
6882 if (req->wct < 3) {
6883 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6884 goto out;
6887 tid2 = SVAL(req->vwv+0, 0);
6888 ofun = SVAL(req->vwv+1, 0);
6889 flags = SVAL(req->vwv+2, 0);
6891 p = (const char *)req->buf;
6892 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6893 &status, &source_has_wild);
6894 if (!NT_STATUS_IS_OK(status)) {
6895 reply_nterror(req, status);
6896 goto out;
6898 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6899 &status, &dest_has_wild);
6900 if (!NT_STATUS_IS_OK(status)) {
6901 reply_nterror(req, status);
6902 goto out;
6905 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6907 if (tid2 != conn->cnum) {
6908 /* can't currently handle inter share copies XXXX */
6909 DEBUG(3,("Rejecting inter-share copy\n"));
6910 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6911 goto out;
6914 status = filename_convert(ctx, conn,
6915 req->flags2 & FLAGS2_DFS_PATHNAMES,
6916 fname_src,
6917 UCF_COND_ALLOW_WCARD_LCOMP,
6918 &source_has_wild,
6919 &smb_fname_src);
6920 if (!NT_STATUS_IS_OK(status)) {
6921 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6922 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6923 ERRSRV, ERRbadpath);
6924 goto out;
6926 reply_nterror(req, status);
6927 goto out;
6930 status = filename_convert(ctx, conn,
6931 req->flags2 & FLAGS2_DFS_PATHNAMES,
6932 fname_dst,
6933 UCF_COND_ALLOW_WCARD_LCOMP,
6934 &dest_has_wild,
6935 &smb_fname_dst);
6936 if (!NT_STATUS_IS_OK(status)) {
6937 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6938 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6939 ERRSRV, ERRbadpath);
6940 goto out;
6942 reply_nterror(req, status);
6943 goto out;
6946 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6948 if ((flags&1) && target_is_directory) {
6949 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6950 goto out;
6953 if ((flags&2) && !target_is_directory) {
6954 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6955 goto out;
6958 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6959 /* wants a tree copy! XXXX */
6960 DEBUG(3,("Rejecting tree copy\n"));
6961 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6962 goto out;
6965 /* Split up the directory from the filename/mask. */
6966 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6967 &fname_src_dir, &fname_src_mask);
6968 if (!NT_STATUS_IS_OK(status)) {
6969 reply_nterror(req, NT_STATUS_NO_MEMORY);
6970 goto out;
6974 * We should only check the mangled cache
6975 * here if unix_convert failed. This means
6976 * that the path in 'mask' doesn't exist
6977 * on the file system and so we need to look
6978 * for a possible mangle. This patch from
6979 * Tine Smukavec <valentin.smukavec@hermes.si>.
6981 if (!VALID_STAT(smb_fname_src->st) &&
6982 mangle_is_mangled(fname_src_mask, conn->params)) {
6983 char *new_mask = NULL;
6984 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6985 &new_mask, conn->params);
6987 /* Use demangled name if one was successfully found. */
6988 if (new_mask) {
6989 TALLOC_FREE(fname_src_mask);
6990 fname_src_mask = new_mask;
6994 if (!source_has_wild) {
6997 * Only one file needs to be copied. Append the mask back onto
6998 * the directory.
7000 TALLOC_FREE(smb_fname_src->base_name);
7001 if (ISDOT(fname_src_dir)) {
7002 /* Ensure we use canonical names on open. */
7003 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7004 "%s",
7005 fname_src_mask);
7006 } else {
7007 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7008 "%s/%s",
7009 fname_src_dir,
7010 fname_src_mask);
7012 if (!smb_fname_src->base_name) {
7013 reply_nterror(req, NT_STATUS_NO_MEMORY);
7014 goto out;
7017 if (dest_has_wild) {
7018 char *fname_dst_mod = NULL;
7019 if (!resolve_wildcards(smb_fname_dst,
7020 smb_fname_src->base_name,
7021 smb_fname_dst->base_name,
7022 &fname_dst_mod)) {
7023 reply_nterror(req, NT_STATUS_NO_MEMORY);
7024 goto out;
7026 TALLOC_FREE(smb_fname_dst->base_name);
7027 smb_fname_dst->base_name = fname_dst_mod;
7030 status = check_name(conn, smb_fname_src->base_name);
7031 if (!NT_STATUS_IS_OK(status)) {
7032 reply_nterror(req, status);
7033 goto out;
7036 status = check_name(conn, smb_fname_dst->base_name);
7037 if (!NT_STATUS_IS_OK(status)) {
7038 reply_nterror(req, status);
7039 goto out;
7042 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7043 ofun, count, target_is_directory);
7045 if(!NT_STATUS_IS_OK(status)) {
7046 reply_nterror(req, status);
7047 goto out;
7048 } else {
7049 count++;
7051 } else {
7052 struct smb_Dir *dir_hnd = NULL;
7053 const char *dname = NULL;
7054 char *talloced = NULL;
7055 long offset = 0;
7058 * There is a wildcard that requires us to actually read the
7059 * src dir and copy each file matching the mask to the dst.
7060 * Right now streams won't be copied, but this could
7061 * presumably be added with a nested loop for reach dir entry.
7063 SMB_ASSERT(!smb_fname_src->stream_name);
7064 SMB_ASSERT(!smb_fname_dst->stream_name);
7066 smb_fname_src->stream_name = NULL;
7067 smb_fname_dst->stream_name = NULL;
7069 if (strequal(fname_src_mask,"????????.???")) {
7070 TALLOC_FREE(fname_src_mask);
7071 fname_src_mask = talloc_strdup(ctx, "*");
7072 if (!fname_src_mask) {
7073 reply_nterror(req, NT_STATUS_NO_MEMORY);
7074 goto out;
7078 status = check_name(conn, fname_src_dir);
7079 if (!NT_STATUS_IS_OK(status)) {
7080 reply_nterror(req, status);
7081 goto out;
7084 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7085 if (dir_hnd == NULL) {
7086 status = map_nt_error_from_unix(errno);
7087 reply_nterror(req, status);
7088 goto out;
7091 error = ERRbadfile;
7093 /* Iterate over the src dir copying each entry to the dst. */
7094 while ((dname = ReadDirName(dir_hnd, &offset,
7095 &smb_fname_src->st, &talloced))) {
7096 char *destname = NULL;
7098 if (ISDOT(dname) || ISDOTDOT(dname)) {
7099 TALLOC_FREE(talloced);
7100 continue;
7103 if (!is_visible_file(conn, fname_src_dir, dname,
7104 &smb_fname_src->st, false)) {
7105 TALLOC_FREE(talloced);
7106 continue;
7109 if(!mask_match(dname, fname_src_mask,
7110 conn->case_sensitive)) {
7111 TALLOC_FREE(talloced);
7112 continue;
7115 error = ERRnoaccess;
7117 /* Get the src smb_fname struct setup. */
7118 TALLOC_FREE(smb_fname_src->base_name);
7119 if (ISDOT(fname_src_dir)) {
7120 /* Ensure we use canonical names on open. */
7121 smb_fname_src->base_name =
7122 talloc_asprintf(smb_fname_src, "%s",
7123 dname);
7124 } else {
7125 smb_fname_src->base_name =
7126 talloc_asprintf(smb_fname_src, "%s/%s",
7127 fname_src_dir, dname);
7130 if (!smb_fname_src->base_name) {
7131 TALLOC_FREE(dir_hnd);
7132 TALLOC_FREE(talloced);
7133 reply_nterror(req, NT_STATUS_NO_MEMORY);
7134 goto out;
7137 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7138 smb_fname_dst->base_name,
7139 &destname)) {
7140 TALLOC_FREE(talloced);
7141 continue;
7143 if (!destname) {
7144 TALLOC_FREE(dir_hnd);
7145 TALLOC_FREE(talloced);
7146 reply_nterror(req, NT_STATUS_NO_MEMORY);
7147 goto out;
7150 TALLOC_FREE(smb_fname_dst->base_name);
7151 smb_fname_dst->base_name = destname;
7153 status = check_name(conn, smb_fname_src->base_name);
7154 if (!NT_STATUS_IS_OK(status)) {
7155 TALLOC_FREE(dir_hnd);
7156 TALLOC_FREE(talloced);
7157 reply_nterror(req, status);
7158 goto out;
7161 status = check_name(conn, smb_fname_dst->base_name);
7162 if (!NT_STATUS_IS_OK(status)) {
7163 TALLOC_FREE(dir_hnd);
7164 TALLOC_FREE(talloced);
7165 reply_nterror(req, status);
7166 goto out;
7169 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7170 smb_fname_src->base_name,
7171 smb_fname_dst->base_name));
7173 status = copy_file(ctx, conn, smb_fname_src,
7174 smb_fname_dst, ofun, count,
7175 target_is_directory);
7176 if (NT_STATUS_IS_OK(status)) {
7177 count++;
7180 TALLOC_FREE(talloced);
7182 TALLOC_FREE(dir_hnd);
7185 if (count == 0) {
7186 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7187 goto out;
7190 reply_outbuf(req, 1, 0);
7191 SSVAL(req->outbuf,smb_vwv0,count);
7192 out:
7193 TALLOC_FREE(smb_fname_src);
7194 TALLOC_FREE(smb_fname_dst);
7195 TALLOC_FREE(fname_src);
7196 TALLOC_FREE(fname_dst);
7197 TALLOC_FREE(fname_src_mask);
7198 TALLOC_FREE(fname_src_dir);
7200 END_PROFILE(SMBcopy);
7201 return;
7204 #undef DBGC_CLASS
7205 #define DBGC_CLASS DBGC_LOCKING
7207 /****************************************************************************
7208 Get a lock pid, dealing with large count requests.
7209 ****************************************************************************/
7211 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7212 bool large_file_format)
7214 if(!large_file_format)
7215 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7216 else
7217 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7220 /****************************************************************************
7221 Get a lock count, dealing with large count requests.
7222 ****************************************************************************/
7224 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7225 bool large_file_format)
7227 uint64_t count = 0;
7229 if(!large_file_format) {
7230 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7231 } else {
7233 #if defined(HAVE_LONGLONG)
7234 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7235 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7236 #else /* HAVE_LONGLONG */
7239 * NT4.x seems to be broken in that it sends large file (64 bit)
7240 * lockingX calls even if the CAP_LARGE_FILES was *not*
7241 * negotiated. For boxes without large unsigned ints truncate the
7242 * lock count by dropping the top 32 bits.
7245 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7246 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7247 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7248 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7249 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7252 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7253 #endif /* HAVE_LONGLONG */
7256 return count;
7259 #if !defined(HAVE_LONGLONG)
7260 /****************************************************************************
7261 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7262 ****************************************************************************/
7264 static uint32 map_lock_offset(uint32 high, uint32 low)
7266 unsigned int i;
7267 uint32 mask = 0;
7268 uint32 highcopy = high;
7271 * Try and find out how many significant bits there are in high.
7274 for(i = 0; highcopy; i++)
7275 highcopy >>= 1;
7278 * We use 31 bits not 32 here as POSIX
7279 * lock offsets may not be negative.
7282 mask = (~0) << (31 - i);
7284 if(low & mask)
7285 return 0; /* Fail. */
7287 high <<= (31 - i);
7289 return (high|low);
7291 #endif /* !defined(HAVE_LONGLONG) */
7293 /****************************************************************************
7294 Get a lock offset, dealing with large offset requests.
7295 ****************************************************************************/
7297 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7298 bool large_file_format, bool *err)
7300 uint64_t offset = 0;
7302 *err = False;
7304 if(!large_file_format) {
7305 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7306 } else {
7308 #if defined(HAVE_LONGLONG)
7309 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7310 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7311 #else /* HAVE_LONGLONG */
7314 * NT4.x seems to be broken in that it sends large file (64 bit)
7315 * lockingX calls even if the CAP_LARGE_FILES was *not*
7316 * negotiated. For boxes without large unsigned ints mangle the
7317 * lock offset by mapping the top 32 bits onto the lower 32.
7320 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7321 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7322 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7323 uint32 new_low = 0;
7325 if((new_low = map_lock_offset(high, low)) == 0) {
7326 *err = True;
7327 return (uint64_t)-1;
7330 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7331 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7332 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7333 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7336 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7337 #endif /* HAVE_LONGLONG */
7340 return offset;
7343 NTSTATUS smbd_do_locking(struct smb_request *req,
7344 files_struct *fsp,
7345 uint8_t type,
7346 int32_t timeout,
7347 uint16_t num_ulocks,
7348 struct smbd_lock_element *ulocks,
7349 uint16_t num_locks,
7350 struct smbd_lock_element *locks,
7351 bool *async)
7353 connection_struct *conn = req->conn;
7354 int i;
7355 NTSTATUS status = NT_STATUS_OK;
7357 *async = false;
7359 /* Data now points at the beginning of the list
7360 of smb_unlkrng structs */
7361 for(i = 0; i < (int)num_ulocks; i++) {
7362 struct smbd_lock_element *e = &ulocks[i];
7364 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7365 "pid %u, file %s\n",
7366 (double)e->offset,
7367 (double)e->count,
7368 (unsigned int)e->smblctx,
7369 fsp_str_dbg(fsp)));
7371 if (e->brltype != UNLOCK_LOCK) {
7372 /* this can only happen with SMB2 */
7373 return NT_STATUS_INVALID_PARAMETER;
7376 status = do_unlock(req->sconn->msg_ctx,
7377 fsp,
7378 e->smblctx,
7379 e->count,
7380 e->offset,
7381 WINDOWS_LOCK);
7383 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7384 nt_errstr(status)));
7386 if (!NT_STATUS_IS_OK(status)) {
7387 return status;
7391 /* Setup the timeout in seconds. */
7393 if (!lp_blocking_locks(SNUM(conn))) {
7394 timeout = 0;
7397 /* Data now points at the beginning of the list
7398 of smb_lkrng structs */
7400 for(i = 0; i < (int)num_locks; i++) {
7401 struct smbd_lock_element *e = &locks[i];
7403 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7404 "%llu, file %s timeout = %d\n",
7405 (double)e->offset,
7406 (double)e->count,
7407 (unsigned long long)e->smblctx,
7408 fsp_str_dbg(fsp),
7409 (int)timeout));
7411 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7412 struct blocking_lock_record *blr = NULL;
7414 if (num_locks > 1) {
7416 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7417 * if the lock vector contains one entry. When given mutliple cancel
7418 * requests in a single PDU we expect the server to return an
7419 * error. Windows servers seem to accept the request but only
7420 * cancel the first lock.
7421 * JRA - Do what Windows does (tm) :-).
7424 #if 0
7425 /* MS-CIFS (2.2.4.32.1) behavior. */
7426 return NT_STATUS_DOS(ERRDOS,
7427 ERRcancelviolation);
7428 #else
7429 /* Windows behavior. */
7430 if (i != 0) {
7431 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7432 "cancel request\n"));
7433 continue;
7435 #endif
7438 if (lp_blocking_locks(SNUM(conn))) {
7440 /* Schedule a message to ourselves to
7441 remove the blocking lock record and
7442 return the right error. */
7444 blr = blocking_lock_cancel_smb1(fsp,
7445 e->smblctx,
7446 e->offset,
7447 e->count,
7448 WINDOWS_LOCK,
7449 type,
7450 NT_STATUS_FILE_LOCK_CONFLICT);
7451 if (blr == NULL) {
7452 return NT_STATUS_DOS(
7453 ERRDOS,
7454 ERRcancelviolation);
7457 /* Remove a matching pending lock. */
7458 status = do_lock_cancel(fsp,
7459 e->smblctx,
7460 e->count,
7461 e->offset,
7462 WINDOWS_LOCK,
7463 blr);
7464 } else {
7465 bool blocking_lock = timeout ? true : false;
7466 bool defer_lock = false;
7467 struct byte_range_lock *br_lck;
7468 uint64_t block_smblctx;
7470 br_lck = do_lock(req->sconn->msg_ctx,
7471 fsp,
7472 e->smblctx,
7473 e->count,
7474 e->offset,
7475 e->brltype,
7476 WINDOWS_LOCK,
7477 blocking_lock,
7478 &status,
7479 &block_smblctx,
7480 NULL);
7482 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7483 /* Windows internal resolution for blocking locks seems
7484 to be about 200ms... Don't wait for less than that. JRA. */
7485 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7486 timeout = lp_lock_spin_time();
7488 defer_lock = true;
7491 /* If a lock sent with timeout of zero would fail, and
7492 * this lock has been requested multiple times,
7493 * according to brl_lock_failed() we convert this
7494 * request to a blocking lock with a timeout of between
7495 * 150 - 300 milliseconds.
7497 * If lp_lock_spin_time() has been set to 0, we skip
7498 * this blocking retry and fail immediately.
7500 * Replacement for do_lock_spin(). JRA. */
7502 if (!req->sconn->using_smb2 &&
7503 br_lck && lp_blocking_locks(SNUM(conn)) &&
7504 lp_lock_spin_time() && !blocking_lock &&
7505 NT_STATUS_EQUAL((status),
7506 NT_STATUS_FILE_LOCK_CONFLICT))
7508 defer_lock = true;
7509 timeout = lp_lock_spin_time();
7512 if (br_lck && defer_lock) {
7514 * A blocking lock was requested. Package up
7515 * this smb into a queued request and push it
7516 * onto the blocking lock queue.
7518 if(push_blocking_lock_request(br_lck,
7519 req,
7520 fsp,
7521 timeout,
7523 e->smblctx,
7524 e->brltype,
7525 WINDOWS_LOCK,
7526 e->offset,
7527 e->count,
7528 block_smblctx)) {
7529 TALLOC_FREE(br_lck);
7530 *async = true;
7531 return NT_STATUS_OK;
7535 TALLOC_FREE(br_lck);
7538 if (!NT_STATUS_IS_OK(status)) {
7539 break;
7543 /* If any of the above locks failed, then we must unlock
7544 all of the previous locks (X/Open spec). */
7546 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7548 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7549 i = -1; /* we want to skip the for loop */
7553 * Ensure we don't do a remove on the lock that just failed,
7554 * as under POSIX rules, if we have a lock already there, we
7555 * will delete it (and we shouldn't) .....
7557 for(i--; i >= 0; i--) {
7558 struct smbd_lock_element *e = &locks[i];
7560 do_unlock(req->sconn->msg_ctx,
7561 fsp,
7562 e->smblctx,
7563 e->count,
7564 e->offset,
7565 WINDOWS_LOCK);
7567 return status;
7570 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7571 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7573 return NT_STATUS_OK;
7576 /****************************************************************************
7577 Reply to a lockingX request.
7578 ****************************************************************************/
7580 void reply_lockingX(struct smb_request *req)
7582 connection_struct *conn = req->conn;
7583 files_struct *fsp;
7584 unsigned char locktype;
7585 unsigned char oplocklevel;
7586 uint16 num_ulocks;
7587 uint16 num_locks;
7588 int32 lock_timeout;
7589 int i;
7590 const uint8_t *data;
7591 bool large_file_format;
7592 bool err;
7593 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7594 struct smbd_lock_element *ulocks;
7595 struct smbd_lock_element *locks;
7596 bool async = false;
7598 START_PROFILE(SMBlockingX);
7600 if (req->wct < 8) {
7601 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7602 END_PROFILE(SMBlockingX);
7603 return;
7606 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7607 locktype = CVAL(req->vwv+3, 0);
7608 oplocklevel = CVAL(req->vwv+3, 1);
7609 num_ulocks = SVAL(req->vwv+6, 0);
7610 num_locks = SVAL(req->vwv+7, 0);
7611 lock_timeout = IVAL(req->vwv+4, 0);
7612 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7614 if (!check_fsp(conn, req, fsp)) {
7615 END_PROFILE(SMBlockingX);
7616 return;
7619 data = req->buf;
7621 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7622 /* we don't support these - and CANCEL_LOCK makes w2k
7623 and XP reboot so I don't really want to be
7624 compatible! (tridge) */
7625 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7626 END_PROFILE(SMBlockingX);
7627 return;
7630 /* Check if this is an oplock break on a file
7631 we have granted an oplock on.
7633 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7634 /* Client can insist on breaking to none. */
7635 bool break_to_none = (oplocklevel == 0);
7636 bool result;
7638 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7639 "for fnum = %d\n", (unsigned int)oplocklevel,
7640 fsp->fnum ));
7643 * Make sure we have granted an exclusive or batch oplock on
7644 * this file.
7647 if (fsp->oplock_type == 0) {
7649 /* The Samba4 nbench simulator doesn't understand
7650 the difference between break to level2 and break
7651 to none from level2 - it sends oplock break
7652 replies in both cases. Don't keep logging an error
7653 message here - just ignore it. JRA. */
7655 DEBUG(5,("reply_lockingX: Error : oplock break from "
7656 "client for fnum = %d (oplock=%d) and no "
7657 "oplock granted on this file (%s).\n",
7658 fsp->fnum, fsp->oplock_type,
7659 fsp_str_dbg(fsp)));
7661 /* if this is a pure oplock break request then don't
7662 * send a reply */
7663 if (num_locks == 0 && num_ulocks == 0) {
7664 END_PROFILE(SMBlockingX);
7665 return;
7666 } else {
7667 END_PROFILE(SMBlockingX);
7668 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7669 return;
7673 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7674 (break_to_none)) {
7675 result = remove_oplock(fsp);
7676 } else {
7677 result = downgrade_oplock(fsp);
7680 if (!result) {
7681 DEBUG(0, ("reply_lockingX: error in removing "
7682 "oplock on file %s\n", fsp_str_dbg(fsp)));
7683 /* Hmmm. Is this panic justified? */
7684 smb_panic("internal tdb error");
7687 reply_to_oplock_break_requests(fsp);
7689 /* if this is a pure oplock break request then don't send a
7690 * reply */
7691 if (num_locks == 0 && num_ulocks == 0) {
7692 /* Sanity check - ensure a pure oplock break is not a
7693 chained request. */
7694 if(CVAL(req->vwv+0, 0) != 0xff)
7695 DEBUG(0,("reply_lockingX: Error : pure oplock "
7696 "break is a chained %d request !\n",
7697 (unsigned int)CVAL(req->vwv+0, 0)));
7698 END_PROFILE(SMBlockingX);
7699 return;
7703 if (req->buflen <
7704 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7706 END_PROFILE(SMBlockingX);
7707 return;
7710 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7711 if (ulocks == NULL) {
7712 reply_nterror(req, NT_STATUS_NO_MEMORY);
7713 END_PROFILE(SMBlockingX);
7714 return;
7717 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7718 if (locks == NULL) {
7719 reply_nterror(req, NT_STATUS_NO_MEMORY);
7720 END_PROFILE(SMBlockingX);
7721 return;
7724 /* Data now points at the beginning of the list
7725 of smb_unlkrng structs */
7726 for(i = 0; i < (int)num_ulocks; i++) {
7727 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7728 ulocks[i].count = get_lock_count(data, i, large_file_format);
7729 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7730 ulocks[i].brltype = UNLOCK_LOCK;
7733 * There is no error code marked "stupid client bug".... :-).
7735 if(err) {
7736 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7737 END_PROFILE(SMBlockingX);
7738 return;
7742 /* Now do any requested locks */
7743 data += ((large_file_format ? 20 : 10)*num_ulocks);
7745 /* Data now points at the beginning of the list
7746 of smb_lkrng structs */
7748 for(i = 0; i < (int)num_locks; i++) {
7749 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7750 locks[i].count = get_lock_count(data, i, large_file_format);
7751 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7753 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7754 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7755 locks[i].brltype = PENDING_READ_LOCK;
7756 } else {
7757 locks[i].brltype = READ_LOCK;
7759 } else {
7760 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7761 locks[i].brltype = PENDING_WRITE_LOCK;
7762 } else {
7763 locks[i].brltype = WRITE_LOCK;
7768 * There is no error code marked "stupid client bug".... :-).
7770 if(err) {
7771 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7772 END_PROFILE(SMBlockingX);
7773 return;
7777 status = smbd_do_locking(req, fsp,
7778 locktype, lock_timeout,
7779 num_ulocks, ulocks,
7780 num_locks, locks,
7781 &async);
7782 if (!NT_STATUS_IS_OK(status)) {
7783 END_PROFILE(SMBlockingX);
7784 reply_nterror(req, status);
7785 return;
7787 if (async) {
7788 END_PROFILE(SMBlockingX);
7789 return;
7792 reply_outbuf(req, 2, 0);
7793 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
7794 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
7796 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7797 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7799 END_PROFILE(SMBlockingX);
7802 #undef DBGC_CLASS
7803 #define DBGC_CLASS DBGC_ALL
7805 /****************************************************************************
7806 Reply to a SMBreadbmpx (read block multiplex) request.
7807 Always reply with an error, if someone has a platform really needs this,
7808 please contact vl@samba.org
7809 ****************************************************************************/
7811 void reply_readbmpx(struct smb_request *req)
7813 START_PROFILE(SMBreadBmpx);
7814 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7815 END_PROFILE(SMBreadBmpx);
7816 return;
7819 /****************************************************************************
7820 Reply to a SMBreadbs (read block multiplex secondary) request.
7821 Always reply with an error, if someone has a platform really needs this,
7822 please contact vl@samba.org
7823 ****************************************************************************/
7825 void reply_readbs(struct smb_request *req)
7827 START_PROFILE(SMBreadBs);
7828 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7829 END_PROFILE(SMBreadBs);
7830 return;
7833 /****************************************************************************
7834 Reply to a SMBsetattrE.
7835 ****************************************************************************/
7837 void reply_setattrE(struct smb_request *req)
7839 connection_struct *conn = req->conn;
7840 struct smb_file_time ft;
7841 files_struct *fsp;
7842 NTSTATUS status;
7844 START_PROFILE(SMBsetattrE);
7845 ZERO_STRUCT(ft);
7847 if (req->wct < 7) {
7848 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7849 goto out;
7852 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7854 if(!fsp || (fsp->conn != conn)) {
7855 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7856 goto out;
7860 * Convert the DOS times into unix times.
7863 ft.atime = convert_time_t_to_timespec(
7864 srv_make_unix_date2(req->vwv+3));
7865 ft.mtime = convert_time_t_to_timespec(
7866 srv_make_unix_date2(req->vwv+5));
7867 ft.create_time = convert_time_t_to_timespec(
7868 srv_make_unix_date2(req->vwv+1));
7870 reply_outbuf(req, 0, 0);
7873 * Patch from Ray Frush <frush@engr.colostate.edu>
7874 * Sometimes times are sent as zero - ignore them.
7877 /* Ensure we have a valid stat struct for the source. */
7878 status = vfs_stat_fsp(fsp);
7879 if (!NT_STATUS_IS_OK(status)) {
7880 reply_nterror(req, status);
7881 goto out;
7884 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
7885 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7886 goto out;
7889 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7890 if (!NT_STATUS_IS_OK(status)) {
7891 reply_nterror(req, status);
7892 goto out;
7895 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7896 " createtime=%u\n",
7897 fsp->fnum,
7898 (unsigned int)ft.atime.tv_sec,
7899 (unsigned int)ft.mtime.tv_sec,
7900 (unsigned int)ft.create_time.tv_sec
7902 out:
7903 END_PROFILE(SMBsetattrE);
7904 return;
7908 /* Back from the dead for OS/2..... JRA. */
7910 /****************************************************************************
7911 Reply to a SMBwritebmpx (write block multiplex primary) request.
7912 Always reply with an error, if someone has a platform really needs this,
7913 please contact vl@samba.org
7914 ****************************************************************************/
7916 void reply_writebmpx(struct smb_request *req)
7918 START_PROFILE(SMBwriteBmpx);
7919 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7920 END_PROFILE(SMBwriteBmpx);
7921 return;
7924 /****************************************************************************
7925 Reply to a SMBwritebs (write block multiplex secondary) request.
7926 Always reply with an error, if someone has a platform really needs this,
7927 please contact vl@samba.org
7928 ****************************************************************************/
7930 void reply_writebs(struct smb_request *req)
7932 START_PROFILE(SMBwriteBs);
7933 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7934 END_PROFILE(SMBwriteBs);
7935 return;
7938 /****************************************************************************
7939 Reply to a SMBgetattrE.
7940 ****************************************************************************/
7942 void reply_getattrE(struct smb_request *req)
7944 connection_struct *conn = req->conn;
7945 int mode;
7946 files_struct *fsp;
7947 struct timespec create_ts;
7949 START_PROFILE(SMBgetattrE);
7951 if (req->wct < 1) {
7952 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7953 END_PROFILE(SMBgetattrE);
7954 return;
7957 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7959 if(!fsp || (fsp->conn != conn)) {
7960 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7961 END_PROFILE(SMBgetattrE);
7962 return;
7965 /* Do an fstat on this file */
7966 if(fsp_stat(fsp)) {
7967 reply_nterror(req, map_nt_error_from_unix(errno));
7968 END_PROFILE(SMBgetattrE);
7969 return;
7972 mode = dos_mode(conn, fsp->fsp_name);
7975 * Convert the times into dos times. Set create
7976 * date to be last modify date as UNIX doesn't save
7977 * this.
7980 reply_outbuf(req, 11, 0);
7982 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7983 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7984 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7985 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7986 /* Should we check pending modtime here ? JRA */
7987 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7988 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7990 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
7991 SIVAL(req->outbuf, smb_vwv6, 0);
7992 SIVAL(req->outbuf, smb_vwv8, 0);
7993 } else {
7994 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7995 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7996 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7998 SSVAL(req->outbuf,smb_vwv10, mode);
8000 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
8002 END_PROFILE(SMBgetattrE);
8003 return;