s3:include: change smb_request->vuid to uint64_t
[Samba.git] / source3 / smbd / reply.c
blob2ea41b4c41da9b5266f67b51d9f50d0e78bdd498
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 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
949 srvstr_push((char *)req->outbuf, req->flags2, p+2,
950 lp_netbios_name(), 15,
951 STR_TERMINATE|STR_ASCII);
952 if (conn) {
953 srvstr_push((char *)req->outbuf, req->flags2,
954 p+18, lp_servicename(SNUM(conn)),
955 13, STR_TERMINATE|STR_ASCII);
956 } else {
957 memset(p+18, 0, 13);
959 break;
963 END_PROFILE(SMBioctl);
964 return;
967 /****************************************************************************
968 Strange checkpath NTSTATUS mapping.
969 ****************************************************************************/
971 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
973 /* Strange DOS error code semantics only for checkpath... */
974 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
975 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
976 /* We need to map to ERRbadpath */
977 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
980 return status;
983 /****************************************************************************
984 Reply to a checkpath.
985 ****************************************************************************/
987 void reply_checkpath(struct smb_request *req)
989 connection_struct *conn = req->conn;
990 struct smb_filename *smb_fname = NULL;
991 char *name = NULL;
992 NTSTATUS status;
993 TALLOC_CTX *ctx = talloc_tos();
995 START_PROFILE(SMBcheckpath);
997 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
998 STR_TERMINATE, &status);
1000 if (!NT_STATUS_IS_OK(status)) {
1001 status = map_checkpath_error(req->flags2, status);
1002 reply_nterror(req, status);
1003 END_PROFILE(SMBcheckpath);
1004 return;
1007 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1009 status = filename_convert(ctx,
1010 conn,
1011 req->flags2 & FLAGS2_DFS_PATHNAMES,
1012 name,
1014 NULL,
1015 &smb_fname);
1017 if (!NT_STATUS_IS_OK(status)) {
1018 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1019 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1020 ERRSRV, ERRbadpath);
1021 END_PROFILE(SMBcheckpath);
1022 return;
1024 goto path_err;
1027 if (!VALID_STAT(smb_fname->st) &&
1028 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1029 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1030 smb_fname_str_dbg(smb_fname), strerror(errno)));
1031 status = map_nt_error_from_unix(errno);
1032 goto path_err;
1035 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1036 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1037 ERRDOS, ERRbadpath);
1038 goto out;
1041 reply_outbuf(req, 0, 0);
1043 path_err:
1044 /* We special case this - as when a Windows machine
1045 is parsing a path is steps through the components
1046 one at a time - if a component fails it expects
1047 ERRbadpath, not ERRbadfile.
1049 status = map_checkpath_error(req->flags2, status);
1050 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1052 * Windows returns different error codes if
1053 * the parent directory is valid but not the
1054 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1055 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1056 * if the path is invalid.
1058 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1059 ERRDOS, ERRbadpath);
1060 goto out;
1063 reply_nterror(req, status);
1065 out:
1066 TALLOC_FREE(smb_fname);
1067 END_PROFILE(SMBcheckpath);
1068 return;
1071 /****************************************************************************
1072 Reply to a getatr.
1073 ****************************************************************************/
1075 void reply_getatr(struct smb_request *req)
1077 connection_struct *conn = req->conn;
1078 struct smb_filename *smb_fname = NULL;
1079 char *fname = NULL;
1080 int mode=0;
1081 off_t size=0;
1082 time_t mtime=0;
1083 const char *p;
1084 NTSTATUS status;
1085 TALLOC_CTX *ctx = talloc_tos();
1086 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1088 START_PROFILE(SMBgetatr);
1090 p = (const char *)req->buf + 1;
1091 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1092 if (!NT_STATUS_IS_OK(status)) {
1093 reply_nterror(req, status);
1094 goto out;
1097 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1098 under WfWg - weird! */
1099 if (*fname == '\0') {
1100 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1101 if (!CAN_WRITE(conn)) {
1102 mode |= FILE_ATTRIBUTE_READONLY;
1104 size = 0;
1105 mtime = 0;
1106 } else {
1107 status = filename_convert(ctx,
1108 conn,
1109 req->flags2 & FLAGS2_DFS_PATHNAMES,
1110 fname,
1112 NULL,
1113 &smb_fname);
1114 if (!NT_STATUS_IS_OK(status)) {
1115 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1116 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1117 ERRSRV, ERRbadpath);
1118 goto out;
1120 reply_nterror(req, status);
1121 goto out;
1123 if (!VALID_STAT(smb_fname->st) &&
1124 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1125 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1126 smb_fname_str_dbg(smb_fname),
1127 strerror(errno)));
1128 reply_nterror(req, map_nt_error_from_unix(errno));
1129 goto out;
1132 mode = dos_mode(conn, smb_fname);
1133 size = smb_fname->st.st_ex_size;
1135 if (ask_sharemode) {
1136 struct timespec write_time_ts;
1137 struct file_id fileid;
1139 ZERO_STRUCT(write_time_ts);
1140 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1141 get_file_infos(fileid, 0, NULL, &write_time_ts);
1142 if (!null_timespec(write_time_ts)) {
1143 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1147 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1148 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1149 size = 0;
1153 reply_outbuf(req, 10, 0);
1155 SSVAL(req->outbuf,smb_vwv0,mode);
1156 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1157 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1158 } else {
1159 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1161 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1163 if (get_Protocol() >= PROTOCOL_NT1) {
1164 SSVAL(req->outbuf, smb_flg2,
1165 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1168 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1169 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1171 out:
1172 TALLOC_FREE(smb_fname);
1173 TALLOC_FREE(fname);
1174 END_PROFILE(SMBgetatr);
1175 return;
1178 /****************************************************************************
1179 Reply to a setatr.
1180 ****************************************************************************/
1182 void reply_setatr(struct smb_request *req)
1184 struct smb_file_time ft;
1185 connection_struct *conn = req->conn;
1186 struct smb_filename *smb_fname = NULL;
1187 char *fname = NULL;
1188 int mode;
1189 time_t mtime;
1190 const char *p;
1191 NTSTATUS status;
1192 TALLOC_CTX *ctx = talloc_tos();
1194 START_PROFILE(SMBsetatr);
1196 ZERO_STRUCT(ft);
1198 if (req->wct < 2) {
1199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1200 goto out;
1203 p = (const char *)req->buf + 1;
1204 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1205 if (!NT_STATUS_IS_OK(status)) {
1206 reply_nterror(req, status);
1207 goto out;
1210 status = filename_convert(ctx,
1211 conn,
1212 req->flags2 & FLAGS2_DFS_PATHNAMES,
1213 fname,
1215 NULL,
1216 &smb_fname);
1217 if (!NT_STATUS_IS_OK(status)) {
1218 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1219 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1220 ERRSRV, ERRbadpath);
1221 goto out;
1223 reply_nterror(req, status);
1224 goto out;
1227 if (smb_fname->base_name[0] == '.' &&
1228 smb_fname->base_name[1] == '\0') {
1230 * Not sure here is the right place to catch this
1231 * condition. Might be moved to somewhere else later -- vl
1233 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1234 goto out;
1237 mode = SVAL(req->vwv+0, 0);
1238 mtime = srv_make_unix_date3(req->vwv+1);
1240 if (mode != FILE_ATTRIBUTE_NORMAL) {
1241 if (VALID_STAT_OF_DIR(smb_fname->st))
1242 mode |= FILE_ATTRIBUTE_DIRECTORY;
1243 else
1244 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1246 status = check_access(conn, NULL, smb_fname,
1247 FILE_WRITE_ATTRIBUTES);
1248 if (!NT_STATUS_IS_OK(status)) {
1249 reply_nterror(req, status);
1250 goto out;
1253 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1254 false) != 0) {
1255 reply_nterror(req, map_nt_error_from_unix(errno));
1256 goto out;
1260 ft.mtime = convert_time_t_to_timespec(mtime);
1261 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1262 if (!NT_STATUS_IS_OK(status)) {
1263 reply_nterror(req, status);
1264 goto out;
1267 reply_outbuf(req, 0, 0);
1269 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1270 mode));
1271 out:
1272 TALLOC_FREE(smb_fname);
1273 END_PROFILE(SMBsetatr);
1274 return;
1277 /****************************************************************************
1278 Reply to a dskattr.
1279 ****************************************************************************/
1281 void reply_dskattr(struct smb_request *req)
1283 connection_struct *conn = req->conn;
1284 uint64_t dfree,dsize,bsize;
1285 START_PROFILE(SMBdskattr);
1287 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1288 reply_nterror(req, map_nt_error_from_unix(errno));
1289 END_PROFILE(SMBdskattr);
1290 return;
1293 reply_outbuf(req, 5, 0);
1295 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1296 double total_space, free_space;
1297 /* we need to scale this to a number that DOS6 can handle. We
1298 use floating point so we can handle large drives on systems
1299 that don't have 64 bit integers
1301 we end up displaying a maximum of 2G to DOS systems
1303 total_space = dsize * (double)bsize;
1304 free_space = dfree * (double)bsize;
1306 dsize = (uint64_t)((total_space+63*512) / (64*512));
1307 dfree = (uint64_t)((free_space+63*512) / (64*512));
1309 if (dsize > 0xFFFF) dsize = 0xFFFF;
1310 if (dfree > 0xFFFF) dfree = 0xFFFF;
1312 SSVAL(req->outbuf,smb_vwv0,dsize);
1313 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1314 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1315 SSVAL(req->outbuf,smb_vwv3,dfree);
1316 } else {
1317 SSVAL(req->outbuf,smb_vwv0,dsize);
1318 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1319 SSVAL(req->outbuf,smb_vwv2,512);
1320 SSVAL(req->outbuf,smb_vwv3,dfree);
1323 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1325 END_PROFILE(SMBdskattr);
1326 return;
1330 * Utility function to split the filename from the directory.
1332 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1333 char **fname_dir_out,
1334 char **fname_mask_out)
1336 const char *p = NULL;
1337 char *fname_dir = NULL;
1338 char *fname_mask = NULL;
1340 p = strrchr_m(fname_in, '/');
1341 if (!p) {
1342 fname_dir = talloc_strdup(ctx, ".");
1343 fname_mask = talloc_strdup(ctx, fname_in);
1344 } else {
1345 fname_dir = talloc_strndup(ctx, fname_in,
1346 PTR_DIFF(p, fname_in));
1347 fname_mask = talloc_strdup(ctx, p+1);
1350 if (!fname_dir || !fname_mask) {
1351 TALLOC_FREE(fname_dir);
1352 TALLOC_FREE(fname_mask);
1353 return NT_STATUS_NO_MEMORY;
1356 *fname_dir_out = fname_dir;
1357 *fname_mask_out = fname_mask;
1358 return NT_STATUS_OK;
1361 /****************************************************************************
1362 Reply to a search.
1363 Can be called from SMBsearch, SMBffirst or SMBfunique.
1364 ****************************************************************************/
1366 void reply_search(struct smb_request *req)
1368 connection_struct *conn = req->conn;
1369 char *path = NULL;
1370 const char *mask = NULL;
1371 char *directory = NULL;
1372 struct smb_filename *smb_fname = NULL;
1373 char *fname = NULL;
1374 off_t size;
1375 uint32 mode;
1376 struct timespec date;
1377 uint32 dirtype;
1378 unsigned int numentries = 0;
1379 unsigned int maxentries = 0;
1380 bool finished = False;
1381 const char *p;
1382 int status_len;
1383 char status[21];
1384 int dptr_num= -1;
1385 bool check_descend = False;
1386 bool expect_close = False;
1387 NTSTATUS nt_status;
1388 bool mask_contains_wcard = False;
1389 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1390 TALLOC_CTX *ctx = talloc_tos();
1391 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1392 struct dptr_struct *dirptr = NULL;
1393 struct smbd_server_connection *sconn = req->sconn;
1395 START_PROFILE(SMBsearch);
1397 if (req->wct < 2) {
1398 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1399 goto out;
1402 if (lp_posix_pathnames()) {
1403 reply_unknown_new(req, req->cmd);
1404 goto out;
1407 /* If we were called as SMBffirst then we must expect close. */
1408 if(req->cmd == SMBffirst) {
1409 expect_close = True;
1412 reply_outbuf(req, 1, 3);
1413 maxentries = SVAL(req->vwv+0, 0);
1414 dirtype = SVAL(req->vwv+1, 0);
1415 p = (const char *)req->buf + 1;
1416 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1417 &nt_status, &mask_contains_wcard);
1418 if (!NT_STATUS_IS_OK(nt_status)) {
1419 reply_nterror(req, nt_status);
1420 goto out;
1423 p++;
1424 status_len = SVAL(p, 0);
1425 p += 2;
1427 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1429 if (status_len == 0) {
1430 nt_status = filename_convert(ctx, conn,
1431 req->flags2 & FLAGS2_DFS_PATHNAMES,
1432 path,
1433 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1434 &mask_contains_wcard,
1435 &smb_fname);
1436 if (!NT_STATUS_IS_OK(nt_status)) {
1437 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1438 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1439 ERRSRV, ERRbadpath);
1440 goto out;
1442 reply_nterror(req, nt_status);
1443 goto out;
1446 directory = smb_fname->base_name;
1448 p = strrchr_m(directory,'/');
1449 if ((p != NULL) && (*directory != '/')) {
1450 mask = p + 1;
1451 directory = talloc_strndup(ctx, directory,
1452 PTR_DIFF(p, directory));
1453 } else {
1454 mask = directory;
1455 directory = talloc_strdup(ctx,".");
1458 if (!directory) {
1459 reply_nterror(req, NT_STATUS_NO_MEMORY);
1460 goto out;
1463 memset((char *)status,'\0',21);
1464 SCVAL(status,0,(dirtype & 0x1F));
1466 nt_status = dptr_create(conn,
1467 NULL, /* req */
1468 NULL, /* fsp */
1469 directory,
1470 True,
1471 expect_close,
1472 req->smbpid,
1473 mask,
1474 mask_contains_wcard,
1475 dirtype,
1476 &dirptr);
1477 if (!NT_STATUS_IS_OK(nt_status)) {
1478 reply_nterror(req, nt_status);
1479 goto out;
1481 dptr_num = dptr_dnum(dirptr);
1482 } else {
1483 int status_dirtype;
1484 const char *dirpath;
1486 memcpy(status,p,21);
1487 status_dirtype = CVAL(status,0) & 0x1F;
1488 if (status_dirtype != (dirtype & 0x1F)) {
1489 dirtype = status_dirtype;
1492 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1493 if (!dirptr) {
1494 goto SearchEmpty;
1496 dirpath = dptr_path(sconn, dptr_num);
1497 directory = talloc_strdup(ctx, dirpath);
1498 if (!directory) {
1499 reply_nterror(req, NT_STATUS_NO_MEMORY);
1500 goto out;
1503 mask = dptr_wcard(sconn, dptr_num);
1504 if (!mask) {
1505 goto SearchEmpty;
1508 * For a 'continue' search we have no string. So
1509 * check from the initial saved string.
1511 mask_contains_wcard = ms_has_wild(mask);
1512 dirtype = dptr_attr(sconn, dptr_num);
1515 DEBUG(4,("dptr_num is %d\n",dptr_num));
1517 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1518 dptr_init_search_op(dirptr);
1520 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1521 char buf[DIR_STRUCT_SIZE];
1522 memcpy(buf,status,21);
1523 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1524 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1525 reply_nterror(req, NT_STATUS_NO_MEMORY);
1526 goto out;
1528 dptr_fill(sconn, buf+12,dptr_num);
1529 if (dptr_zero(buf+12) && (status_len==0)) {
1530 numentries = 1;
1531 } else {
1532 numentries = 0;
1534 if (message_push_blob(&req->outbuf,
1535 data_blob_const(buf, sizeof(buf)))
1536 == -1) {
1537 reply_nterror(req, NT_STATUS_NO_MEMORY);
1538 goto out;
1540 } else {
1541 unsigned int i;
1542 maxentries = MIN(
1543 maxentries,
1544 ((BUFFER_SIZE -
1545 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1546 /DIR_STRUCT_SIZE));
1548 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1549 directory,lp_dontdescend(SNUM(conn))));
1550 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1551 check_descend = True;
1554 for (i=numentries;(i<maxentries) && !finished;i++) {
1555 finished = !get_dir_entry(ctx,
1556 dirptr,
1557 mask,
1558 dirtype,
1559 &fname,
1560 &size,
1561 &mode,
1562 &date,
1563 check_descend,
1564 ask_sharemode);
1565 if (!finished) {
1566 char buf[DIR_STRUCT_SIZE];
1567 memcpy(buf,status,21);
1568 if (!make_dir_struct(ctx,
1569 buf,
1570 mask,
1571 fname,
1572 size,
1573 mode,
1574 convert_timespec_to_time_t(date),
1575 !allow_long_path_components)) {
1576 reply_nterror(req, NT_STATUS_NO_MEMORY);
1577 goto out;
1579 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1580 break;
1582 if (message_push_blob(&req->outbuf,
1583 data_blob_const(buf, sizeof(buf)))
1584 == -1) {
1585 reply_nterror(req, NT_STATUS_NO_MEMORY);
1586 goto out;
1588 numentries++;
1593 SearchEmpty:
1595 /* If we were called as SMBffirst with smb_search_id == NULL
1596 and no entries were found then return error and close dirptr
1597 (X/Open spec) */
1599 if (numentries == 0) {
1600 dptr_close(sconn, &dptr_num);
1601 } else if(expect_close && status_len == 0) {
1602 /* Close the dptr - we know it's gone */
1603 dptr_close(sconn, &dptr_num);
1606 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1607 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1608 dptr_close(sconn, &dptr_num);
1611 if ((numentries == 0) && !mask_contains_wcard) {
1612 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1613 goto out;
1616 SSVAL(req->outbuf,smb_vwv0,numentries);
1617 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1618 SCVAL(smb_buf(req->outbuf),0,5);
1619 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1621 /* The replies here are never long name. */
1622 SSVAL(req->outbuf, smb_flg2,
1623 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1624 if (!allow_long_path_components) {
1625 SSVAL(req->outbuf, smb_flg2,
1626 SVAL(req->outbuf, smb_flg2)
1627 & (~FLAGS2_LONG_PATH_COMPONENTS));
1630 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1631 SSVAL(req->outbuf, smb_flg2,
1632 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1634 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1635 smb_fn_name(req->cmd),
1636 mask,
1637 directory,
1638 dirtype,
1639 numentries,
1640 maxentries ));
1641 out:
1642 TALLOC_FREE(directory);
1643 TALLOC_FREE(smb_fname);
1644 END_PROFILE(SMBsearch);
1645 return;
1648 /****************************************************************************
1649 Reply to a fclose (stop directory search).
1650 ****************************************************************************/
1652 void reply_fclose(struct smb_request *req)
1654 int status_len;
1655 char status[21];
1656 int dptr_num= -2;
1657 const char *p;
1658 char *path = NULL;
1659 NTSTATUS err;
1660 bool path_contains_wcard = False;
1661 TALLOC_CTX *ctx = talloc_tos();
1662 struct smbd_server_connection *sconn = req->sconn;
1664 START_PROFILE(SMBfclose);
1666 if (lp_posix_pathnames()) {
1667 reply_unknown_new(req, req->cmd);
1668 END_PROFILE(SMBfclose);
1669 return;
1672 p = (const char *)req->buf + 1;
1673 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1674 &err, &path_contains_wcard);
1675 if (!NT_STATUS_IS_OK(err)) {
1676 reply_nterror(req, err);
1677 END_PROFILE(SMBfclose);
1678 return;
1680 p++;
1681 status_len = SVAL(p,0);
1682 p += 2;
1684 if (status_len == 0) {
1685 reply_force_doserror(req, ERRSRV, ERRsrverror);
1686 END_PROFILE(SMBfclose);
1687 return;
1690 memcpy(status,p,21);
1692 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1693 /* Close the dptr - we know it's gone */
1694 dptr_close(sconn, &dptr_num);
1697 reply_outbuf(req, 1, 0);
1698 SSVAL(req->outbuf,smb_vwv0,0);
1700 DEBUG(3,("search close\n"));
1702 END_PROFILE(SMBfclose);
1703 return;
1706 /****************************************************************************
1707 Reply to an open.
1708 ****************************************************************************/
1710 void reply_open(struct smb_request *req)
1712 connection_struct *conn = req->conn;
1713 struct smb_filename *smb_fname = NULL;
1714 char *fname = NULL;
1715 uint32 fattr=0;
1716 off_t size = 0;
1717 time_t mtime=0;
1718 int info;
1719 files_struct *fsp;
1720 int oplock_request;
1721 int deny_mode;
1722 uint32 dos_attr;
1723 uint32 access_mask;
1724 uint32 share_mode;
1725 uint32 create_disposition;
1726 uint32 create_options = 0;
1727 uint32_t private_flags = 0;
1728 NTSTATUS status;
1729 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1730 TALLOC_CTX *ctx = talloc_tos();
1732 START_PROFILE(SMBopen);
1734 if (req->wct < 2) {
1735 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1736 goto out;
1739 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1740 deny_mode = SVAL(req->vwv+0, 0);
1741 dos_attr = SVAL(req->vwv+1, 0);
1743 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1744 STR_TERMINATE, &status);
1745 if (!NT_STATUS_IS_OK(status)) {
1746 reply_nterror(req, status);
1747 goto out;
1750 status = filename_convert(ctx,
1751 conn,
1752 req->flags2 & FLAGS2_DFS_PATHNAMES,
1753 fname,
1755 NULL,
1756 &smb_fname);
1757 if (!NT_STATUS_IS_OK(status)) {
1758 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1759 reply_botherror(req,
1760 NT_STATUS_PATH_NOT_COVERED,
1761 ERRSRV, ERRbadpath);
1762 goto out;
1764 reply_nterror(req, status);
1765 goto out;
1768 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1769 OPENX_FILE_EXISTS_OPEN, &access_mask,
1770 &share_mode, &create_disposition,
1771 &create_options, &private_flags)) {
1772 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1773 goto out;
1776 status = SMB_VFS_CREATE_FILE(
1777 conn, /* conn */
1778 req, /* req */
1779 0, /* root_dir_fid */
1780 smb_fname, /* fname */
1781 access_mask, /* access_mask */
1782 share_mode, /* share_access */
1783 create_disposition, /* create_disposition*/
1784 create_options, /* create_options */
1785 dos_attr, /* file_attributes */
1786 oplock_request, /* oplock_request */
1787 0, /* allocation_size */
1788 private_flags,
1789 NULL, /* sd */
1790 NULL, /* ea_list */
1791 &fsp, /* result */
1792 &info); /* pinfo */
1794 if (!NT_STATUS_IS_OK(status)) {
1795 if (open_was_deferred(req->sconn, req->mid)) {
1796 /* We have re-scheduled this call. */
1797 goto out;
1799 reply_openerror(req, status);
1800 goto out;
1803 size = smb_fname->st.st_ex_size;
1804 fattr = dos_mode(conn, smb_fname);
1806 /* Deal with other possible opens having a modified
1807 write time. JRA. */
1808 if (ask_sharemode) {
1809 struct timespec write_time_ts;
1811 ZERO_STRUCT(write_time_ts);
1812 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1813 if (!null_timespec(write_time_ts)) {
1814 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1818 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1820 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1821 DEBUG(3,("attempt to open a directory %s\n",
1822 fsp_str_dbg(fsp)));
1823 close_file(req, fsp, ERROR_CLOSE);
1824 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1825 ERRDOS, ERRnoaccess);
1826 goto out;
1829 reply_outbuf(req, 7, 0);
1830 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1831 SSVAL(req->outbuf,smb_vwv1,fattr);
1832 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1833 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1834 } else {
1835 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1837 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1838 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1840 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1841 SCVAL(req->outbuf,smb_flg,
1842 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1845 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1846 SCVAL(req->outbuf,smb_flg,
1847 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1849 out:
1850 TALLOC_FREE(smb_fname);
1851 END_PROFILE(SMBopen);
1852 return;
1855 /****************************************************************************
1856 Reply to an open and X.
1857 ****************************************************************************/
1859 void reply_open_and_X(struct smb_request *req)
1861 connection_struct *conn = req->conn;
1862 struct smb_filename *smb_fname = NULL;
1863 char *fname = NULL;
1864 uint16 open_flags;
1865 int deny_mode;
1866 uint32 smb_attr;
1867 /* Breakout the oplock request bits so we can set the
1868 reply bits separately. */
1869 int ex_oplock_request;
1870 int core_oplock_request;
1871 int oplock_request;
1872 #if 0
1873 int smb_sattr = SVAL(req->vwv+4, 0);
1874 uint32 smb_time = make_unix_date3(req->vwv+6);
1875 #endif
1876 int smb_ofun;
1877 uint32 fattr=0;
1878 int mtime=0;
1879 int smb_action = 0;
1880 files_struct *fsp;
1881 NTSTATUS status;
1882 uint64_t allocation_size;
1883 ssize_t retval = -1;
1884 uint32 access_mask;
1885 uint32 share_mode;
1886 uint32 create_disposition;
1887 uint32 create_options = 0;
1888 uint32_t private_flags = 0;
1889 TALLOC_CTX *ctx = talloc_tos();
1891 START_PROFILE(SMBopenX);
1893 if (req->wct < 15) {
1894 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1895 goto out;
1898 open_flags = SVAL(req->vwv+2, 0);
1899 deny_mode = SVAL(req->vwv+3, 0);
1900 smb_attr = SVAL(req->vwv+5, 0);
1901 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1902 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1903 oplock_request = ex_oplock_request | core_oplock_request;
1904 smb_ofun = SVAL(req->vwv+8, 0);
1905 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1907 /* If it's an IPC, pass off the pipe handler. */
1908 if (IS_IPC(conn)) {
1909 if (lp_nt_pipe_support()) {
1910 reply_open_pipe_and_X(conn, req);
1911 } else {
1912 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1914 goto out;
1917 /* XXXX we need to handle passed times, sattr and flags */
1918 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1919 STR_TERMINATE, &status);
1920 if (!NT_STATUS_IS_OK(status)) {
1921 reply_nterror(req, status);
1922 goto out;
1925 status = filename_convert(ctx,
1926 conn,
1927 req->flags2 & FLAGS2_DFS_PATHNAMES,
1928 fname,
1930 NULL,
1931 &smb_fname);
1932 if (!NT_STATUS_IS_OK(status)) {
1933 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1934 reply_botherror(req,
1935 NT_STATUS_PATH_NOT_COVERED,
1936 ERRSRV, ERRbadpath);
1937 goto out;
1939 reply_nterror(req, status);
1940 goto out;
1943 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1944 smb_ofun,
1945 &access_mask, &share_mode,
1946 &create_disposition,
1947 &create_options,
1948 &private_flags)) {
1949 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1950 goto out;
1953 status = SMB_VFS_CREATE_FILE(
1954 conn, /* conn */
1955 req, /* req */
1956 0, /* root_dir_fid */
1957 smb_fname, /* fname */
1958 access_mask, /* access_mask */
1959 share_mode, /* share_access */
1960 create_disposition, /* create_disposition*/
1961 create_options, /* create_options */
1962 smb_attr, /* file_attributes */
1963 oplock_request, /* oplock_request */
1964 0, /* allocation_size */
1965 private_flags,
1966 NULL, /* sd */
1967 NULL, /* ea_list */
1968 &fsp, /* result */
1969 &smb_action); /* pinfo */
1971 if (!NT_STATUS_IS_OK(status)) {
1972 if (open_was_deferred(req->sconn, req->mid)) {
1973 /* We have re-scheduled this call. */
1974 goto out;
1976 reply_openerror(req, status);
1977 goto out;
1980 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1981 if the file is truncated or created. */
1982 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1983 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1984 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1985 close_file(req, fsp, ERROR_CLOSE);
1986 reply_nterror(req, NT_STATUS_DISK_FULL);
1987 goto out;
1989 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
1990 if (retval < 0) {
1991 close_file(req, fsp, ERROR_CLOSE);
1992 reply_nterror(req, NT_STATUS_DISK_FULL);
1993 goto out;
1995 status = vfs_stat_fsp(fsp);
1996 if (!NT_STATUS_IS_OK(status)) {
1997 close_file(req, fsp, ERROR_CLOSE);
1998 reply_nterror(req, status);
1999 goto out;
2003 fattr = dos_mode(conn, fsp->fsp_name);
2004 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2005 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2006 close_file(req, fsp, ERROR_CLOSE);
2007 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2008 goto out;
2011 /* If the caller set the extended oplock request bit
2012 and we granted one (by whatever means) - set the
2013 correct bit for extended oplock reply.
2016 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2017 smb_action |= EXTENDED_OPLOCK_GRANTED;
2020 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2021 smb_action |= EXTENDED_OPLOCK_GRANTED;
2024 /* If the caller set the core oplock request bit
2025 and we granted one (by whatever means) - set the
2026 correct bit for core oplock reply.
2029 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2030 reply_outbuf(req, 19, 0);
2031 } else {
2032 reply_outbuf(req, 15, 0);
2035 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2036 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2038 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2039 SCVAL(req->outbuf, smb_flg,
2040 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2043 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2044 SCVAL(req->outbuf, smb_flg,
2045 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2048 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2049 SSVAL(req->outbuf,smb_vwv3,fattr);
2050 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2051 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2052 } else {
2053 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2055 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2056 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2057 SSVAL(req->outbuf,smb_vwv11,smb_action);
2059 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2060 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2063 out:
2064 TALLOC_FREE(smb_fname);
2065 END_PROFILE(SMBopenX);
2066 return;
2069 /****************************************************************************
2070 Reply to a SMBulogoffX.
2071 ****************************************************************************/
2073 void reply_ulogoffX(struct smb_request *req)
2075 struct smbd_server_connection *sconn = req->sconn;
2076 struct user_struct *vuser;
2078 START_PROFILE(SMBulogoffX);
2080 vuser = get_valid_user_struct(sconn, req->vuid);
2082 if(vuser == NULL) {
2083 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2084 (unsigned long long)req->vuid));
2086 req->vuid = UID_FIELD_INVALID;
2087 reply_force_doserror(req, ERRSRV, ERRbaduid);
2088 END_PROFILE(SMBulogoffX);
2089 return;
2092 /* in user level security we are supposed to close any files
2093 open by this user */
2094 if (vuser != NULL) {
2095 file_close_user(sconn, req->vuid);
2098 invalidate_vuid(sconn, req->vuid);
2100 reply_outbuf(req, 2, 0);
2101 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2102 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2104 DEBUG(3, ("ulogoffX vuid=%llu\n",
2105 (unsigned long long)req->vuid));
2107 END_PROFILE(SMBulogoffX);
2108 req->vuid = UID_FIELD_INVALID;
2111 /****************************************************************************
2112 Reply to a mknew or a create.
2113 ****************************************************************************/
2115 void reply_mknew(struct smb_request *req)
2117 connection_struct *conn = req->conn;
2118 struct smb_filename *smb_fname = NULL;
2119 char *fname = NULL;
2120 uint32 fattr = 0;
2121 struct smb_file_time ft;
2122 files_struct *fsp;
2123 int oplock_request = 0;
2124 NTSTATUS status;
2125 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2126 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2127 uint32 create_disposition;
2128 uint32 create_options = 0;
2129 TALLOC_CTX *ctx = talloc_tos();
2131 START_PROFILE(SMBcreate);
2132 ZERO_STRUCT(ft);
2134 if (req->wct < 3) {
2135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2136 goto out;
2139 fattr = SVAL(req->vwv+0, 0);
2140 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2142 /* mtime. */
2143 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2145 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2146 STR_TERMINATE, &status);
2147 if (!NT_STATUS_IS_OK(status)) {
2148 reply_nterror(req, status);
2149 goto out;
2152 status = filename_convert(ctx,
2153 conn,
2154 req->flags2 & FLAGS2_DFS_PATHNAMES,
2155 fname,
2157 NULL,
2158 &smb_fname);
2159 if (!NT_STATUS_IS_OK(status)) {
2160 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2161 reply_botherror(req,
2162 NT_STATUS_PATH_NOT_COVERED,
2163 ERRSRV, ERRbadpath);
2164 goto out;
2166 reply_nterror(req, status);
2167 goto out;
2170 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2171 DEBUG(0,("Attempt to create file (%s) with volid set - "
2172 "please report this\n",
2173 smb_fname_str_dbg(smb_fname)));
2176 if(req->cmd == SMBmknew) {
2177 /* We should fail if file exists. */
2178 create_disposition = FILE_CREATE;
2179 } else {
2180 /* Create if file doesn't exist, truncate if it does. */
2181 create_disposition = FILE_OVERWRITE_IF;
2184 status = SMB_VFS_CREATE_FILE(
2185 conn, /* conn */
2186 req, /* req */
2187 0, /* root_dir_fid */
2188 smb_fname, /* fname */
2189 access_mask, /* access_mask */
2190 share_mode, /* share_access */
2191 create_disposition, /* create_disposition*/
2192 create_options, /* create_options */
2193 fattr, /* file_attributes */
2194 oplock_request, /* oplock_request */
2195 0, /* allocation_size */
2196 0, /* private_flags */
2197 NULL, /* sd */
2198 NULL, /* ea_list */
2199 &fsp, /* result */
2200 NULL); /* pinfo */
2202 if (!NT_STATUS_IS_OK(status)) {
2203 if (open_was_deferred(req->sconn, req->mid)) {
2204 /* We have re-scheduled this call. */
2205 goto out;
2207 reply_openerror(req, status);
2208 goto out;
2211 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2212 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2213 if (!NT_STATUS_IS_OK(status)) {
2214 END_PROFILE(SMBcreate);
2215 goto out;
2218 reply_outbuf(req, 1, 0);
2219 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2221 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2222 SCVAL(req->outbuf,smb_flg,
2223 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2226 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2227 SCVAL(req->outbuf,smb_flg,
2228 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2231 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2232 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2233 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2234 (unsigned int)fattr));
2236 out:
2237 TALLOC_FREE(smb_fname);
2238 END_PROFILE(SMBcreate);
2239 return;
2242 /****************************************************************************
2243 Reply to a create temporary file.
2244 ****************************************************************************/
2246 void reply_ctemp(struct smb_request *req)
2248 connection_struct *conn = req->conn;
2249 struct smb_filename *smb_fname = NULL;
2250 char *fname = NULL;
2251 uint32 fattr;
2252 files_struct *fsp;
2253 int oplock_request;
2254 int tmpfd;
2255 char *s;
2256 NTSTATUS status;
2257 TALLOC_CTX *ctx = talloc_tos();
2259 START_PROFILE(SMBctemp);
2261 if (req->wct < 3) {
2262 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2263 goto out;
2266 fattr = SVAL(req->vwv+0, 0);
2267 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2269 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2270 STR_TERMINATE, &status);
2271 if (!NT_STATUS_IS_OK(status)) {
2272 reply_nterror(req, status);
2273 goto out;
2275 if (*fname) {
2276 fname = talloc_asprintf(ctx,
2277 "%s/TMXXXXXX",
2278 fname);
2279 } else {
2280 fname = talloc_strdup(ctx, "TMXXXXXX");
2283 if (!fname) {
2284 reply_nterror(req, NT_STATUS_NO_MEMORY);
2285 goto out;
2288 status = filename_convert(ctx, conn,
2289 req->flags2 & FLAGS2_DFS_PATHNAMES,
2290 fname,
2292 NULL,
2293 &smb_fname);
2294 if (!NT_STATUS_IS_OK(status)) {
2295 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2296 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2297 ERRSRV, ERRbadpath);
2298 goto out;
2300 reply_nterror(req, status);
2301 goto out;
2304 tmpfd = mkstemp(smb_fname->base_name);
2305 if (tmpfd == -1) {
2306 reply_nterror(req, map_nt_error_from_unix(errno));
2307 goto out;
2310 SMB_VFS_STAT(conn, smb_fname);
2312 /* We should fail if file does not exist. */
2313 status = SMB_VFS_CREATE_FILE(
2314 conn, /* conn */
2315 req, /* req */
2316 0, /* root_dir_fid */
2317 smb_fname, /* fname */
2318 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2319 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2320 FILE_OPEN, /* create_disposition*/
2321 0, /* create_options */
2322 fattr, /* file_attributes */
2323 oplock_request, /* oplock_request */
2324 0, /* allocation_size */
2325 0, /* private_flags */
2326 NULL, /* sd */
2327 NULL, /* ea_list */
2328 &fsp, /* result */
2329 NULL); /* pinfo */
2331 /* close fd from mkstemp() */
2332 close(tmpfd);
2334 if (!NT_STATUS_IS_OK(status)) {
2335 if (open_was_deferred(req->sconn, req->mid)) {
2336 /* We have re-scheduled this call. */
2337 goto out;
2339 reply_openerror(req, status);
2340 goto out;
2343 reply_outbuf(req, 1, 0);
2344 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2346 /* the returned filename is relative to the directory */
2347 s = strrchr_m(fsp->fsp_name->base_name, '/');
2348 if (!s) {
2349 s = fsp->fsp_name->base_name;
2350 } else {
2351 s++;
2354 #if 0
2355 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2356 thing in the byte section. JRA */
2357 SSVALS(p, 0, -1); /* what is this? not in spec */
2358 #endif
2359 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2360 == -1) {
2361 reply_nterror(req, NT_STATUS_NO_MEMORY);
2362 goto out;
2365 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2366 SCVAL(req->outbuf, smb_flg,
2367 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2370 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2371 SCVAL(req->outbuf, smb_flg,
2372 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2375 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2376 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2377 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2378 out:
2379 TALLOC_FREE(smb_fname);
2380 END_PROFILE(SMBctemp);
2381 return;
2384 /*******************************************************************
2385 Check if a user is allowed to rename a file.
2386 ********************************************************************/
2388 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2389 uint16 dirtype)
2391 if (!CAN_WRITE(conn)) {
2392 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2395 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2396 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2397 /* Only bother to read the DOS attribute if we might deny the
2398 rename on the grounds of attribute missmatch. */
2399 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2400 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2401 return NT_STATUS_NO_SUCH_FILE;
2405 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2406 if (fsp->posix_open) {
2407 return NT_STATUS_OK;
2410 /* If no pathnames are open below this
2411 directory, allow the rename. */
2413 if (file_find_subpath(fsp)) {
2414 return NT_STATUS_ACCESS_DENIED;
2416 return NT_STATUS_OK;
2419 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2420 return NT_STATUS_OK;
2423 return NT_STATUS_ACCESS_DENIED;
2426 /*******************************************************************
2427 * unlink a file with all relevant access checks
2428 *******************************************************************/
2430 static NTSTATUS do_unlink(connection_struct *conn,
2431 struct smb_request *req,
2432 struct smb_filename *smb_fname,
2433 uint32 dirtype)
2435 uint32 fattr;
2436 files_struct *fsp;
2437 uint32 dirtype_orig = dirtype;
2438 NTSTATUS status;
2439 int ret;
2440 bool posix_paths = lp_posix_pathnames();
2442 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2443 smb_fname_str_dbg(smb_fname),
2444 dirtype));
2446 if (!CAN_WRITE(conn)) {
2447 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2450 if (posix_paths) {
2451 ret = SMB_VFS_LSTAT(conn, smb_fname);
2452 } else {
2453 ret = SMB_VFS_STAT(conn, smb_fname);
2455 if (ret != 0) {
2456 return map_nt_error_from_unix(errno);
2459 fattr = dos_mode(conn, smb_fname);
2461 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2462 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2465 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2466 if (!dirtype) {
2467 return NT_STATUS_NO_SUCH_FILE;
2470 if (!dir_check_ftype(conn, fattr, dirtype)) {
2471 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2472 return NT_STATUS_FILE_IS_A_DIRECTORY;
2474 return NT_STATUS_NO_SUCH_FILE;
2477 if (dirtype_orig & 0x8000) {
2478 /* These will never be set for POSIX. */
2479 return NT_STATUS_NO_SUCH_FILE;
2482 #if 0
2483 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2484 return NT_STATUS_FILE_IS_A_DIRECTORY;
2487 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2488 return NT_STATUS_NO_SUCH_FILE;
2491 if (dirtype & 0xFF00) {
2492 /* These will never be set for POSIX. */
2493 return NT_STATUS_NO_SUCH_FILE;
2496 dirtype &= 0xFF;
2497 if (!dirtype) {
2498 return NT_STATUS_NO_SUCH_FILE;
2501 /* Can't delete a directory. */
2502 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2503 return NT_STATUS_FILE_IS_A_DIRECTORY;
2505 #endif
2507 #if 0 /* JRATEST */
2508 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2509 return NT_STATUS_OBJECT_NAME_INVALID;
2510 #endif /* JRATEST */
2512 /* On open checks the open itself will check the share mode, so
2513 don't do it here as we'll get it wrong. */
2515 status = SMB_VFS_CREATE_FILE
2516 (conn, /* conn */
2517 req, /* req */
2518 0, /* root_dir_fid */
2519 smb_fname, /* fname */
2520 DELETE_ACCESS, /* access_mask */
2521 FILE_SHARE_NONE, /* share_access */
2522 FILE_OPEN, /* create_disposition*/
2523 FILE_NON_DIRECTORY_FILE, /* create_options */
2524 /* file_attributes */
2525 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2526 FILE_ATTRIBUTE_NORMAL,
2527 0, /* oplock_request */
2528 0, /* allocation_size */
2529 0, /* private_flags */
2530 NULL, /* sd */
2531 NULL, /* ea_list */
2532 &fsp, /* result */
2533 NULL); /* pinfo */
2535 if (!NT_STATUS_IS_OK(status)) {
2536 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2537 nt_errstr(status)));
2538 return status;
2541 status = can_set_delete_on_close(fsp, fattr);
2542 if (!NT_STATUS_IS_OK(status)) {
2543 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2544 "(%s)\n",
2545 smb_fname_str_dbg(smb_fname),
2546 nt_errstr(status)));
2547 close_file(req, fsp, NORMAL_CLOSE);
2548 return status;
2551 /* The set is across all open files on this dev/inode pair. */
2552 if (!set_delete_on_close(fsp, True,
2553 conn->session_info->security_token,
2554 conn->session_info->unix_token)) {
2555 close_file(req, fsp, NORMAL_CLOSE);
2556 return NT_STATUS_ACCESS_DENIED;
2559 return close_file(req, fsp, NORMAL_CLOSE);
2562 /****************************************************************************
2563 The guts of the unlink command, split out so it may be called by the NT SMB
2564 code.
2565 ****************************************************************************/
2567 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2568 uint32 dirtype, struct smb_filename *smb_fname,
2569 bool has_wild)
2571 char *fname_dir = NULL;
2572 char *fname_mask = NULL;
2573 int count=0;
2574 NTSTATUS status = NT_STATUS_OK;
2575 TALLOC_CTX *ctx = talloc_tos();
2577 /* Split up the directory from the filename/mask. */
2578 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2579 &fname_dir, &fname_mask);
2580 if (!NT_STATUS_IS_OK(status)) {
2581 goto out;
2585 * We should only check the mangled cache
2586 * here if unix_convert failed. This means
2587 * that the path in 'mask' doesn't exist
2588 * on the file system and so we need to look
2589 * for a possible mangle. This patch from
2590 * Tine Smukavec <valentin.smukavec@hermes.si>.
2593 if (!VALID_STAT(smb_fname->st) &&
2594 mangle_is_mangled(fname_mask, conn->params)) {
2595 char *new_mask = NULL;
2596 mangle_lookup_name_from_8_3(ctx, fname_mask,
2597 &new_mask, conn->params);
2598 if (new_mask) {
2599 TALLOC_FREE(fname_mask);
2600 fname_mask = new_mask;
2604 if (!has_wild) {
2607 * Only one file needs to be unlinked. Append the mask back
2608 * onto the directory.
2610 TALLOC_FREE(smb_fname->base_name);
2611 if (ISDOT(fname_dir)) {
2612 /* Ensure we use canonical names on open. */
2613 smb_fname->base_name = talloc_asprintf(smb_fname,
2614 "%s",
2615 fname_mask);
2616 } else {
2617 smb_fname->base_name = talloc_asprintf(smb_fname,
2618 "%s/%s",
2619 fname_dir,
2620 fname_mask);
2622 if (!smb_fname->base_name) {
2623 status = NT_STATUS_NO_MEMORY;
2624 goto out;
2626 if (dirtype == 0) {
2627 dirtype = FILE_ATTRIBUTE_NORMAL;
2630 status = check_name(conn, smb_fname->base_name);
2631 if (!NT_STATUS_IS_OK(status)) {
2632 goto out;
2635 status = do_unlink(conn, req, smb_fname, dirtype);
2636 if (!NT_STATUS_IS_OK(status)) {
2637 goto out;
2640 count++;
2641 } else {
2642 struct smb_Dir *dir_hnd = NULL;
2643 long offset = 0;
2644 const char *dname = NULL;
2645 char *talloced = NULL;
2647 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2648 status = NT_STATUS_OBJECT_NAME_INVALID;
2649 goto out;
2652 if (strequal(fname_mask,"????????.???")) {
2653 TALLOC_FREE(fname_mask);
2654 fname_mask = talloc_strdup(ctx, "*");
2655 if (!fname_mask) {
2656 status = NT_STATUS_NO_MEMORY;
2657 goto out;
2661 status = check_name(conn, fname_dir);
2662 if (!NT_STATUS_IS_OK(status)) {
2663 goto out;
2666 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2667 dirtype);
2668 if (dir_hnd == NULL) {
2669 status = map_nt_error_from_unix(errno);
2670 goto out;
2673 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2674 the pattern matches against the long name, otherwise the short name
2675 We don't implement this yet XXXX
2678 status = NT_STATUS_NO_SUCH_FILE;
2680 while ((dname = ReadDirName(dir_hnd, &offset,
2681 &smb_fname->st, &talloced))) {
2682 TALLOC_CTX *frame = talloc_stackframe();
2684 if (!is_visible_file(conn, fname_dir, dname,
2685 &smb_fname->st, true)) {
2686 TALLOC_FREE(frame);
2687 TALLOC_FREE(talloced);
2688 continue;
2691 /* Quick check for "." and ".." */
2692 if (ISDOT(dname) || ISDOTDOT(dname)) {
2693 TALLOC_FREE(frame);
2694 TALLOC_FREE(talloced);
2695 continue;
2698 if(!mask_match(dname, fname_mask,
2699 conn->case_sensitive)) {
2700 TALLOC_FREE(frame);
2701 TALLOC_FREE(talloced);
2702 continue;
2705 TALLOC_FREE(smb_fname->base_name);
2706 if (ISDOT(fname_dir)) {
2707 /* Ensure we use canonical names on open. */
2708 smb_fname->base_name =
2709 talloc_asprintf(smb_fname, "%s",
2710 dname);
2711 } else {
2712 smb_fname->base_name =
2713 talloc_asprintf(smb_fname, "%s/%s",
2714 fname_dir, dname);
2717 if (!smb_fname->base_name) {
2718 TALLOC_FREE(dir_hnd);
2719 status = NT_STATUS_NO_MEMORY;
2720 TALLOC_FREE(frame);
2721 TALLOC_FREE(talloced);
2722 goto out;
2725 status = check_name(conn, smb_fname->base_name);
2726 if (!NT_STATUS_IS_OK(status)) {
2727 TALLOC_FREE(dir_hnd);
2728 TALLOC_FREE(frame);
2729 TALLOC_FREE(talloced);
2730 goto out;
2733 status = do_unlink(conn, req, smb_fname, dirtype);
2734 if (!NT_STATUS_IS_OK(status)) {
2735 TALLOC_FREE(frame);
2736 TALLOC_FREE(talloced);
2737 continue;
2740 count++;
2741 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2742 smb_fname->base_name));
2744 TALLOC_FREE(frame);
2745 TALLOC_FREE(talloced);
2747 TALLOC_FREE(dir_hnd);
2750 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2751 status = map_nt_error_from_unix(errno);
2754 out:
2755 TALLOC_FREE(fname_dir);
2756 TALLOC_FREE(fname_mask);
2757 return status;
2760 /****************************************************************************
2761 Reply to a unlink
2762 ****************************************************************************/
2764 void reply_unlink(struct smb_request *req)
2766 connection_struct *conn = req->conn;
2767 char *name = NULL;
2768 struct smb_filename *smb_fname = NULL;
2769 uint32 dirtype;
2770 NTSTATUS status;
2771 bool path_contains_wcard = False;
2772 TALLOC_CTX *ctx = talloc_tos();
2774 START_PROFILE(SMBunlink);
2776 if (req->wct < 1) {
2777 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2778 goto out;
2781 dirtype = SVAL(req->vwv+0, 0);
2783 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2784 STR_TERMINATE, &status,
2785 &path_contains_wcard);
2786 if (!NT_STATUS_IS_OK(status)) {
2787 reply_nterror(req, status);
2788 goto out;
2791 status = filename_convert(ctx, conn,
2792 req->flags2 & FLAGS2_DFS_PATHNAMES,
2793 name,
2794 UCF_COND_ALLOW_WCARD_LCOMP,
2795 &path_contains_wcard,
2796 &smb_fname);
2797 if (!NT_STATUS_IS_OK(status)) {
2798 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2799 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2800 ERRSRV, ERRbadpath);
2801 goto out;
2803 reply_nterror(req, status);
2804 goto out;
2807 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2809 status = unlink_internals(conn, req, dirtype, smb_fname,
2810 path_contains_wcard);
2811 if (!NT_STATUS_IS_OK(status)) {
2812 if (open_was_deferred(req->sconn, req->mid)) {
2813 /* We have re-scheduled this call. */
2814 goto out;
2816 reply_nterror(req, status);
2817 goto out;
2820 reply_outbuf(req, 0, 0);
2821 out:
2822 TALLOC_FREE(smb_fname);
2823 END_PROFILE(SMBunlink);
2824 return;
2827 /****************************************************************************
2828 Fail for readbraw.
2829 ****************************************************************************/
2831 static void fail_readraw(void)
2833 const char *errstr = talloc_asprintf(talloc_tos(),
2834 "FAIL ! reply_readbraw: socket write fail (%s)",
2835 strerror(errno));
2836 if (!errstr) {
2837 errstr = "";
2839 exit_server_cleanly(errstr);
2842 /****************************************************************************
2843 Fake (read/write) sendfile. Returns -1 on read or write fail.
2844 ****************************************************************************/
2846 ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread)
2848 size_t bufsize;
2849 size_t tosend = nread;
2850 char *buf;
2852 if (nread == 0) {
2853 return 0;
2856 bufsize = MIN(nread, 65536);
2858 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2859 return -1;
2862 while (tosend > 0) {
2863 ssize_t ret;
2864 size_t cur_read;
2866 if (tosend > bufsize) {
2867 cur_read = bufsize;
2868 } else {
2869 cur_read = tosend;
2871 ret = read_file(fsp,buf,startpos,cur_read);
2872 if (ret == -1) {
2873 SAFE_FREE(buf);
2874 return -1;
2877 /* If we had a short read, fill with zeros. */
2878 if (ret < cur_read) {
2879 memset(buf + ret, '\0', cur_read - ret);
2882 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2883 != cur_read) {
2884 char addr[INET6_ADDRSTRLEN];
2886 * Try and give an error message saying what
2887 * client failed.
2889 DEBUG(0, ("write_data failed for client %s. "
2890 "Error %s\n",
2891 get_peer_addr(fsp->conn->sconn->sock, addr,
2892 sizeof(addr)),
2893 strerror(errno)));
2894 SAFE_FREE(buf);
2895 return -1;
2897 tosend -= cur_read;
2898 startpos += cur_read;
2901 SAFE_FREE(buf);
2902 return (ssize_t)nread;
2905 /****************************************************************************
2906 Deal with the case of sendfile reading less bytes from the file than
2907 requested. Fill with zeros (all we can do).
2908 ****************************************************************************/
2910 void sendfile_short_send(files_struct *fsp,
2911 ssize_t nread,
2912 size_t headersize,
2913 size_t smb_maxcnt)
2915 #define SHORT_SEND_BUFSIZE 1024
2916 if (nread < headersize) {
2917 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2918 "header for file %s (%s). Terminating\n",
2919 fsp_str_dbg(fsp), strerror(errno)));
2920 exit_server_cleanly("sendfile_short_send failed");
2923 nread -= headersize;
2925 if (nread < smb_maxcnt) {
2926 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2927 if (!buf) {
2928 exit_server_cleanly("sendfile_short_send: "
2929 "malloc failed");
2932 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2933 "with zeros !\n", fsp_str_dbg(fsp)));
2935 while (nread < smb_maxcnt) {
2937 * We asked for the real file size and told sendfile
2938 * to not go beyond the end of the file. But it can
2939 * happen that in between our fstat call and the
2940 * sendfile call the file was truncated. This is very
2941 * bad because we have already announced the larger
2942 * number of bytes to the client.
2944 * The best we can do now is to send 0-bytes, just as
2945 * a read from a hole in a sparse file would do.
2947 * This should happen rarely enough that I don't care
2948 * about efficiency here :-)
2950 size_t to_write;
2952 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2953 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2954 != to_write) {
2955 char addr[INET6_ADDRSTRLEN];
2957 * Try and give an error message saying what
2958 * client failed.
2960 DEBUG(0, ("write_data failed for client %s. "
2961 "Error %s\n",
2962 get_peer_addr(
2963 fsp->conn->sconn->sock, addr,
2964 sizeof(addr)),
2965 strerror(errno)));
2966 exit_server_cleanly("sendfile_short_send: "
2967 "write_data failed");
2969 nread += to_write;
2971 SAFE_FREE(buf);
2975 /****************************************************************************
2976 Return a readbraw error (4 bytes of zero).
2977 ****************************************************************************/
2979 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2981 char header[4];
2983 SIVAL(header,0,0);
2985 smbd_lock_socket(sconn);
2986 if (write_data(sconn->sock,header,4) != 4) {
2987 char addr[INET6_ADDRSTRLEN];
2989 * Try and give an error message saying what
2990 * client failed.
2992 DEBUG(0, ("write_data failed for client %s. "
2993 "Error %s\n",
2994 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2995 strerror(errno)));
2997 fail_readraw();
2999 smbd_unlock_socket(sconn);
3002 /****************************************************************************
3003 Use sendfile in readbraw.
3004 ****************************************************************************/
3006 static void send_file_readbraw(connection_struct *conn,
3007 struct smb_request *req,
3008 files_struct *fsp,
3009 off_t startpos,
3010 size_t nread,
3011 ssize_t mincount)
3013 struct smbd_server_connection *sconn = req->sconn;
3014 char *outbuf = NULL;
3015 ssize_t ret=0;
3018 * We can only use sendfile on a non-chained packet
3019 * but we can use on a non-oplocked file. tridge proved this
3020 * on a train in Germany :-). JRA.
3021 * reply_readbraw has already checked the length.
3024 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3025 (fsp->wcp == NULL) &&
3026 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3027 ssize_t sendfile_read = -1;
3028 char header[4];
3029 DATA_BLOB header_blob;
3031 _smb_setlen(header,nread);
3032 header_blob = data_blob_const(header, 4);
3034 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3035 &header_blob, startpos,
3036 nread);
3037 if (sendfile_read == -1) {
3038 /* Returning ENOSYS means no data at all was sent.
3039 * Do this as a normal read. */
3040 if (errno == ENOSYS) {
3041 goto normal_readbraw;
3045 * Special hack for broken Linux with no working sendfile. If we
3046 * return EINTR we sent the header but not the rest of the data.
3047 * Fake this up by doing read/write calls.
3049 if (errno == EINTR) {
3050 /* Ensure we don't do this again. */
3051 set_use_sendfile(SNUM(conn), False);
3052 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3054 if (fake_sendfile(fsp, startpos, nread) == -1) {
3055 DEBUG(0,("send_file_readbraw: "
3056 "fake_sendfile failed for "
3057 "file %s (%s).\n",
3058 fsp_str_dbg(fsp),
3059 strerror(errno)));
3060 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3062 return;
3065 DEBUG(0,("send_file_readbraw: sendfile failed for "
3066 "file %s (%s). Terminating\n",
3067 fsp_str_dbg(fsp), strerror(errno)));
3068 exit_server_cleanly("send_file_readbraw sendfile failed");
3069 } else if (sendfile_read == 0) {
3071 * Some sendfile implementations return 0 to indicate
3072 * that there was a short read, but nothing was
3073 * actually written to the socket. In this case,
3074 * fallback to the normal read path so the header gets
3075 * the correct byte count.
3077 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3078 "bytes falling back to the normal read: "
3079 "%s\n", fsp_str_dbg(fsp)));
3080 goto normal_readbraw;
3083 /* Deal with possible short send. */
3084 if (sendfile_read != 4+nread) {
3085 sendfile_short_send(fsp, sendfile_read, 4, nread);
3087 return;
3090 normal_readbraw:
3092 outbuf = talloc_array(NULL, char, nread+4);
3093 if (!outbuf) {
3094 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3095 (unsigned)(nread+4)));
3096 reply_readbraw_error(sconn);
3097 return;
3100 if (nread > 0) {
3101 ret = read_file(fsp,outbuf+4,startpos,nread);
3102 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3103 if (ret < mincount)
3104 ret = 0;
3105 #else
3106 if (ret < nread)
3107 ret = 0;
3108 #endif
3111 _smb_setlen(outbuf,ret);
3112 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3113 char addr[INET6_ADDRSTRLEN];
3115 * Try and give an error message saying what
3116 * client failed.
3118 DEBUG(0, ("write_data failed for client %s. "
3119 "Error %s\n",
3120 get_peer_addr(fsp->conn->sconn->sock, addr,
3121 sizeof(addr)),
3122 strerror(errno)));
3124 fail_readraw();
3127 TALLOC_FREE(outbuf);
3130 /****************************************************************************
3131 Reply to a readbraw (core+ protocol).
3132 ****************************************************************************/
3134 void reply_readbraw(struct smb_request *req)
3136 connection_struct *conn = req->conn;
3137 struct smbd_server_connection *sconn = req->sconn;
3138 ssize_t maxcount,mincount;
3139 size_t nread = 0;
3140 off_t startpos;
3141 files_struct *fsp;
3142 struct lock_struct lock;
3143 off_t size = 0;
3145 START_PROFILE(SMBreadbraw);
3147 if (srv_is_signing_active(sconn) ||
3148 is_encrypted_packet(sconn, req->inbuf)) {
3149 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3150 "raw reads/writes are disallowed.");
3153 if (req->wct < 8) {
3154 reply_readbraw_error(sconn);
3155 END_PROFILE(SMBreadbraw);
3156 return;
3159 if (sconn->smb1.echo_handler.trusted_fde) {
3160 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3161 "'async smb echo handler = yes'\n"));
3162 reply_readbraw_error(sconn);
3163 END_PROFILE(SMBreadbraw);
3164 return;
3168 * Special check if an oplock break has been issued
3169 * and the readraw request croses on the wire, we must
3170 * return a zero length response here.
3173 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3176 * We have to do a check_fsp by hand here, as
3177 * we must always return 4 zero bytes on error,
3178 * not a NTSTATUS.
3181 if (!fsp || !conn || conn != fsp->conn ||
3182 req->vuid != fsp->vuid ||
3183 fsp->is_directory || fsp->fh->fd == -1) {
3185 * fsp could be NULL here so use the value from the packet. JRA.
3187 DEBUG(3,("reply_readbraw: fnum %d not valid "
3188 "- cache prime?\n",
3189 (int)SVAL(req->vwv+0, 0)));
3190 reply_readbraw_error(sconn);
3191 END_PROFILE(SMBreadbraw);
3192 return;
3195 /* Do a "by hand" version of CHECK_READ. */
3196 if (!(fsp->can_read ||
3197 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3198 (fsp->access_mask & FILE_EXECUTE)))) {
3199 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3200 (int)SVAL(req->vwv+0, 0)));
3201 reply_readbraw_error(sconn);
3202 END_PROFILE(SMBreadbraw);
3203 return;
3206 flush_write_cache(fsp, READRAW_FLUSH);
3208 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3209 if(req->wct == 10) {
3211 * This is a large offset (64 bit) read.
3214 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3216 if(startpos < 0) {
3217 DEBUG(0,("reply_readbraw: negative 64 bit "
3218 "readraw offset (%.0f) !\n",
3219 (double)startpos ));
3220 reply_readbraw_error(sconn);
3221 END_PROFILE(SMBreadbraw);
3222 return;
3226 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3227 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3229 /* ensure we don't overrun the packet size */
3230 maxcount = MIN(65535,maxcount);
3232 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3233 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3234 &lock);
3236 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3237 reply_readbraw_error(sconn);
3238 END_PROFILE(SMBreadbraw);
3239 return;
3242 if (fsp_stat(fsp) == 0) {
3243 size = fsp->fsp_name->st.st_ex_size;
3246 if (startpos >= size) {
3247 nread = 0;
3248 } else {
3249 nread = MIN(maxcount,(size - startpos));
3252 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3253 if (nread < mincount)
3254 nread = 0;
3255 #endif
3257 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3258 "min=%lu nread=%lu\n",
3259 fsp->fnum, (double)startpos,
3260 (unsigned long)maxcount,
3261 (unsigned long)mincount,
3262 (unsigned long)nread ) );
3264 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3266 DEBUG(5,("reply_readbraw finished\n"));
3268 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3270 END_PROFILE(SMBreadbraw);
3271 return;
3274 #undef DBGC_CLASS
3275 #define DBGC_CLASS DBGC_LOCKING
3277 /****************************************************************************
3278 Reply to a lockread (core+ protocol).
3279 ****************************************************************************/
3281 void reply_lockread(struct smb_request *req)
3283 connection_struct *conn = req->conn;
3284 ssize_t nread = -1;
3285 char *data;
3286 off_t startpos;
3287 size_t numtoread;
3288 NTSTATUS status;
3289 files_struct *fsp;
3290 struct byte_range_lock *br_lck = NULL;
3291 char *p = NULL;
3292 struct smbd_server_connection *sconn = req->sconn;
3294 START_PROFILE(SMBlockread);
3296 if (req->wct < 5) {
3297 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3298 END_PROFILE(SMBlockread);
3299 return;
3302 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3304 if (!check_fsp(conn, req, fsp)) {
3305 END_PROFILE(SMBlockread);
3306 return;
3309 if (!CHECK_READ(fsp,req)) {
3310 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3311 END_PROFILE(SMBlockread);
3312 return;
3315 numtoread = SVAL(req->vwv+1, 0);
3316 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3318 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3320 reply_outbuf(req, 5, numtoread + 3);
3322 data = smb_buf(req->outbuf) + 3;
3325 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3326 * protocol request that predates the read/write lock concept.
3327 * Thus instead of asking for a read lock here we need to ask
3328 * for a write lock. JRA.
3329 * Note that the requested lock size is unaffected by max_recv.
3332 br_lck = do_lock(req->sconn->msg_ctx,
3333 fsp,
3334 (uint64_t)req->smbpid,
3335 (uint64_t)numtoread,
3336 (uint64_t)startpos,
3337 WRITE_LOCK,
3338 WINDOWS_LOCK,
3339 False, /* Non-blocking lock. */
3340 &status,
3341 NULL,
3342 NULL);
3343 TALLOC_FREE(br_lck);
3345 if (NT_STATUS_V(status)) {
3346 reply_nterror(req, status);
3347 END_PROFILE(SMBlockread);
3348 return;
3352 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3355 if (numtoread > sconn->smb1.negprot.max_recv) {
3356 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3357 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3358 (unsigned int)numtoread,
3359 (unsigned int)sconn->smb1.negprot.max_recv));
3360 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3362 nread = read_file(fsp,data,startpos,numtoread);
3364 if (nread < 0) {
3365 reply_nterror(req, map_nt_error_from_unix(errno));
3366 END_PROFILE(SMBlockread);
3367 return;
3370 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3372 SSVAL(req->outbuf,smb_vwv0,nread);
3373 SSVAL(req->outbuf,smb_vwv5,nread+3);
3374 p = smb_buf(req->outbuf);
3375 SCVAL(p,0,0); /* pad byte. */
3376 SSVAL(p,1,nread);
3378 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3379 fsp->fnum, (int)numtoread, (int)nread));
3381 END_PROFILE(SMBlockread);
3382 return;
3385 #undef DBGC_CLASS
3386 #define DBGC_CLASS DBGC_ALL
3388 /****************************************************************************
3389 Reply to a read.
3390 ****************************************************************************/
3392 void reply_read(struct smb_request *req)
3394 connection_struct *conn = req->conn;
3395 size_t numtoread;
3396 ssize_t nread = 0;
3397 char *data;
3398 off_t startpos;
3399 int outsize = 0;
3400 files_struct *fsp;
3401 struct lock_struct lock;
3402 struct smbd_server_connection *sconn = req->sconn;
3404 START_PROFILE(SMBread);
3406 if (req->wct < 3) {
3407 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3408 END_PROFILE(SMBread);
3409 return;
3412 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3414 if (!check_fsp(conn, req, fsp)) {
3415 END_PROFILE(SMBread);
3416 return;
3419 if (!CHECK_READ(fsp,req)) {
3420 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3421 END_PROFILE(SMBread);
3422 return;
3425 numtoread = SVAL(req->vwv+1, 0);
3426 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3428 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3431 * The requested read size cannot be greater than max_recv. JRA.
3433 if (numtoread > sconn->smb1.negprot.max_recv) {
3434 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3435 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3436 (unsigned int)numtoread,
3437 (unsigned int)sconn->smb1.negprot.max_recv));
3438 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3441 reply_outbuf(req, 5, numtoread+3);
3443 data = smb_buf(req->outbuf) + 3;
3445 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3446 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3447 &lock);
3449 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3450 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3451 END_PROFILE(SMBread);
3452 return;
3455 if (numtoread > 0)
3456 nread = read_file(fsp,data,startpos,numtoread);
3458 if (nread < 0) {
3459 reply_nterror(req, map_nt_error_from_unix(errno));
3460 goto strict_unlock;
3463 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3465 SSVAL(req->outbuf,smb_vwv0,nread);
3466 SSVAL(req->outbuf,smb_vwv5,nread+3);
3467 SCVAL(smb_buf(req->outbuf),0,1);
3468 SSVAL(smb_buf(req->outbuf),1,nread);
3470 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3471 fsp->fnum, (int)numtoread, (int)nread ) );
3473 strict_unlock:
3474 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3476 END_PROFILE(SMBread);
3477 return;
3480 /****************************************************************************
3481 Setup readX header.
3482 ****************************************************************************/
3484 static int setup_readX_header(struct smb_request *req, char *outbuf,
3485 size_t smb_maxcnt)
3487 int outsize;
3489 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3491 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3493 SCVAL(outbuf,smb_vwv0,0xFF);
3494 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3495 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3496 SSVAL(outbuf,smb_vwv6,
3497 (smb_wct - 4) /* offset from smb header to wct */
3498 + 1 /* the wct field */
3499 + 12 * sizeof(uint16_t) /* vwv */
3500 + 2); /* the buflen field */
3501 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3502 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3503 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3504 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3505 return outsize;
3508 /****************************************************************************
3509 Reply to a read and X - possibly using sendfile.
3510 ****************************************************************************/
3512 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3513 files_struct *fsp, off_t startpos,
3514 size_t smb_maxcnt)
3516 ssize_t nread = -1;
3517 struct lock_struct lock;
3518 int saved_errno = 0;
3520 if(fsp_stat(fsp) == -1) {
3521 reply_nterror(req, map_nt_error_from_unix(errno));
3522 return;
3525 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3526 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3527 &lock);
3529 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3530 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3531 return;
3534 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3535 (startpos > fsp->fsp_name->st.st_ex_size)
3536 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3538 * We already know that we would do a short read, so don't
3539 * try the sendfile() path.
3541 goto nosendfile_read;
3545 * We can only use sendfile on a non-chained packet
3546 * but we can use on a non-oplocked file. tridge proved this
3547 * on a train in Germany :-). JRA.
3550 if (!req_is_in_chain(req) &&
3551 !is_encrypted_packet(req->sconn, req->inbuf) &&
3552 (fsp->base_fsp == NULL) &&
3553 (fsp->wcp == NULL) &&
3554 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3555 uint8 headerbuf[smb_size + 12 * 2];
3556 DATA_BLOB header;
3559 * Set up the packet header before send. We
3560 * assume here the sendfile will work (get the
3561 * correct amount of data).
3564 header = data_blob_const(headerbuf, sizeof(headerbuf));
3566 construct_reply_common_req(req, (char *)headerbuf);
3567 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3569 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3570 startpos, smb_maxcnt);
3571 if (nread == -1) {
3572 /* Returning ENOSYS means no data at all was sent.
3573 Do this as a normal read. */
3574 if (errno == ENOSYS) {
3575 goto normal_read;
3579 * Special hack for broken Linux with no working sendfile. If we
3580 * return EINTR we sent the header but not the rest of the data.
3581 * Fake this up by doing read/write calls.
3584 if (errno == EINTR) {
3585 /* Ensure we don't do this again. */
3586 set_use_sendfile(SNUM(conn), False);
3587 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3588 nread = fake_sendfile(fsp, startpos,
3589 smb_maxcnt);
3590 if (nread == -1) {
3591 DEBUG(0,("send_file_readX: "
3592 "fake_sendfile failed for "
3593 "file %s (%s).\n",
3594 fsp_str_dbg(fsp),
3595 strerror(errno)));
3596 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3598 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3599 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3600 /* No outbuf here means successful sendfile. */
3601 goto strict_unlock;
3604 DEBUG(0,("send_file_readX: sendfile failed for file "
3605 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3606 strerror(errno)));
3607 exit_server_cleanly("send_file_readX sendfile failed");
3608 } else if (nread == 0) {
3610 * Some sendfile implementations return 0 to indicate
3611 * that there was a short read, but nothing was
3612 * actually written to the socket. In this case,
3613 * fallback to the normal read path so the header gets
3614 * the correct byte count.
3616 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3617 "falling back to the normal read: %s\n",
3618 fsp_str_dbg(fsp)));
3619 goto normal_read;
3622 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3623 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3625 /* Deal with possible short send. */
3626 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3627 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3629 /* No outbuf here means successful sendfile. */
3630 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3631 SMB_PERFCOUNT_END(&req->pcd);
3632 goto strict_unlock;
3635 normal_read:
3637 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3638 uint8 headerbuf[smb_size + 2*12];
3640 construct_reply_common_req(req, (char *)headerbuf);
3641 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3643 /* Send out the header. */
3644 if (write_data(req->sconn->sock, (char *)headerbuf,
3645 sizeof(headerbuf)) != sizeof(headerbuf)) {
3647 char addr[INET6_ADDRSTRLEN];
3649 * Try and give an error message saying what
3650 * client failed.
3652 DEBUG(0, ("write_data failed for client %s. "
3653 "Error %s\n",
3654 get_peer_addr(req->sconn->sock, addr,
3655 sizeof(addr)),
3656 strerror(errno)));
3658 DEBUG(0,("send_file_readX: write_data failed for file "
3659 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3660 strerror(errno)));
3661 exit_server_cleanly("send_file_readX sendfile failed");
3663 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3664 if (nread == -1) {
3665 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3666 "file %s (%s).\n", fsp_str_dbg(fsp),
3667 strerror(errno)));
3668 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3670 goto strict_unlock;
3673 nosendfile_read:
3675 reply_outbuf(req, 12, smb_maxcnt);
3676 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3677 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3679 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3680 saved_errno = errno;
3682 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3684 if (nread < 0) {
3685 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3686 return;
3689 setup_readX_header(req, (char *)req->outbuf, nread);
3691 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3692 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3693 return;
3695 strict_unlock:
3696 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3697 TALLOC_FREE(req->outbuf);
3698 return;
3701 /****************************************************************************
3702 Reply to a read and X.
3703 ****************************************************************************/
3705 void reply_read_and_X(struct smb_request *req)
3707 struct smbd_server_connection *sconn = req->sconn;
3708 connection_struct *conn = req->conn;
3709 files_struct *fsp;
3710 off_t startpos;
3711 size_t smb_maxcnt;
3712 bool big_readX = False;
3713 #if 0
3714 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3715 #endif
3717 START_PROFILE(SMBreadX);
3719 if ((req->wct != 10) && (req->wct != 12)) {
3720 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3721 return;
3724 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3725 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3726 smb_maxcnt = SVAL(req->vwv+5, 0);
3728 /* If it's an IPC, pass off the pipe handler. */
3729 if (IS_IPC(conn)) {
3730 reply_pipe_read_and_X(req);
3731 END_PROFILE(SMBreadX);
3732 return;
3735 if (!check_fsp(conn, req, fsp)) {
3736 END_PROFILE(SMBreadX);
3737 return;
3740 if (!CHECK_READ(fsp,req)) {
3741 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3742 END_PROFILE(SMBreadX);
3743 return;
3746 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_LARGE_READ_CAP) ||
3747 (get_remote_arch() == RA_SAMBA)) {
3749 * This is Samba only behavior (up to Samba 3.6)!
3751 * Windows 2008 R2 ignores the upper_size,
3752 * so we do unless unix extentions are active
3753 * or "smbclient" is talking to us.
3755 size_t upper_size = SVAL(req->vwv+7, 0);
3756 smb_maxcnt |= (upper_size<<16);
3757 if (upper_size > 1) {
3758 /* Can't do this on a chained packet. */
3759 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3760 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3761 END_PROFILE(SMBreadX);
3762 return;
3764 /* We currently don't do this on signed or sealed data. */
3765 if (srv_is_signing_active(req->sconn) ||
3766 is_encrypted_packet(req->sconn, req->inbuf)) {
3767 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3768 END_PROFILE(SMBreadX);
3769 return;
3771 /* Is there room in the reply for this data ? */
3772 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3773 reply_nterror(req,
3774 NT_STATUS_INVALID_PARAMETER);
3775 END_PROFILE(SMBreadX);
3776 return;
3778 big_readX = True;
3782 if (req->wct == 12) {
3784 * This is a large offset (64 bit) read.
3786 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
3790 if (!big_readX) {
3791 NTSTATUS status = schedule_aio_read_and_X(conn,
3792 req,
3793 fsp,
3794 startpos,
3795 smb_maxcnt);
3796 if (NT_STATUS_IS_OK(status)) {
3797 /* Read scheduled - we're done. */
3798 goto out;
3800 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3801 /* Real error - report to client. */
3802 END_PROFILE(SMBreadX);
3803 reply_nterror(req, status);
3804 return;
3806 /* NT_STATUS_RETRY - fall back to sync read. */
3809 smbd_lock_socket(req->sconn);
3810 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3811 smbd_unlock_socket(req->sconn);
3813 out:
3814 END_PROFILE(SMBreadX);
3815 return;
3818 /****************************************************************************
3819 Error replies to writebraw must have smb_wct == 1. Fix this up.
3820 ****************************************************************************/
3822 void error_to_writebrawerr(struct smb_request *req)
3824 uint8 *old_outbuf = req->outbuf;
3826 reply_outbuf(req, 1, 0);
3828 memcpy(req->outbuf, old_outbuf, smb_size);
3829 TALLOC_FREE(old_outbuf);
3832 /****************************************************************************
3833 Read 4 bytes of a smb packet and return the smb length of the packet.
3834 Store the result in the buffer. This version of the function will
3835 never return a session keepalive (length of zero).
3836 Timeout is in milliseconds.
3837 ****************************************************************************/
3839 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3840 size_t *len)
3842 uint8_t msgtype = NBSSkeepalive;
3844 while (msgtype == NBSSkeepalive) {
3845 NTSTATUS status;
3847 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3848 len);
3849 if (!NT_STATUS_IS_OK(status)) {
3850 char addr[INET6_ADDRSTRLEN];
3851 /* Try and give an error message
3852 * saying what client failed. */
3853 DEBUG(0, ("read_fd_with_timeout failed for "
3854 "client %s read error = %s.\n",
3855 get_peer_addr(fd,addr,sizeof(addr)),
3856 nt_errstr(status)));
3857 return status;
3860 msgtype = CVAL(inbuf, 0);
3863 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3864 (unsigned long)len));
3866 return NT_STATUS_OK;
3869 /****************************************************************************
3870 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3871 ****************************************************************************/
3873 void reply_writebraw(struct smb_request *req)
3875 connection_struct *conn = req->conn;
3876 char *buf = NULL;
3877 ssize_t nwritten=0;
3878 ssize_t total_written=0;
3879 size_t numtowrite=0;
3880 size_t tcount;
3881 off_t startpos;
3882 const char *data=NULL;
3883 bool write_through;
3884 files_struct *fsp;
3885 struct lock_struct lock;
3886 NTSTATUS status;
3888 START_PROFILE(SMBwritebraw);
3891 * If we ever reply with an error, it must have the SMB command
3892 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3893 * we're finished.
3895 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3897 if (srv_is_signing_active(req->sconn)) {
3898 END_PROFILE(SMBwritebraw);
3899 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3900 "raw reads/writes are disallowed.");
3903 if (req->wct < 12) {
3904 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3905 error_to_writebrawerr(req);
3906 END_PROFILE(SMBwritebraw);
3907 return;
3910 if (req->sconn->smb1.echo_handler.trusted_fde) {
3911 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3912 "'async smb echo handler = yes'\n"));
3913 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3914 error_to_writebrawerr(req);
3915 END_PROFILE(SMBwritebraw);
3916 return;
3919 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3920 if (!check_fsp(conn, req, fsp)) {
3921 error_to_writebrawerr(req);
3922 END_PROFILE(SMBwritebraw);
3923 return;
3926 if (!CHECK_WRITE(fsp)) {
3927 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3928 error_to_writebrawerr(req);
3929 END_PROFILE(SMBwritebraw);
3930 return;
3933 tcount = IVAL(req->vwv+1, 0);
3934 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3935 write_through = BITSETW(req->vwv+7,0);
3937 /* We have to deal with slightly different formats depending
3938 on whether we are using the core+ or lanman1.0 protocol */
3940 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3941 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3942 data = smb_buf_const(req->inbuf);
3943 } else {
3944 numtowrite = SVAL(req->vwv+10, 0);
3945 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3948 /* Ensure we don't write bytes past the end of this packet. */
3949 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3950 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3951 error_to_writebrawerr(req);
3952 END_PROFILE(SMBwritebraw);
3953 return;
3956 if (!fsp->print_file) {
3957 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3958 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3959 &lock);
3961 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3962 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3963 error_to_writebrawerr(req);
3964 END_PROFILE(SMBwritebraw);
3965 return;
3969 if (numtowrite>0) {
3970 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3973 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3974 "wrote=%d sync=%d\n",
3975 fsp->fnum, (double)startpos, (int)numtowrite,
3976 (int)nwritten, (int)write_through));
3978 if (nwritten < (ssize_t)numtowrite) {
3979 reply_nterror(req, NT_STATUS_DISK_FULL);
3980 error_to_writebrawerr(req);
3981 goto strict_unlock;
3984 total_written = nwritten;
3986 /* Allocate a buffer of 64k + length. */
3987 buf = talloc_array(NULL, char, 65540);
3988 if (!buf) {
3989 reply_nterror(req, NT_STATUS_NO_MEMORY);
3990 error_to_writebrawerr(req);
3991 goto strict_unlock;
3994 /* Return a SMBwritebraw message to the redirector to tell
3995 * it to send more bytes */
3997 memcpy(buf, req->inbuf, smb_size);
3998 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3999 SCVAL(buf,smb_com,SMBwritebraw);
4000 SSVALS(buf,smb_vwv0,0xFFFF);
4001 show_msg(buf);
4002 if (!srv_send_smb(req->sconn,
4003 buf,
4004 false, 0, /* no signing */
4005 IS_CONN_ENCRYPTED(conn),
4006 &req->pcd)) {
4007 exit_server_cleanly("reply_writebraw: srv_send_smb "
4008 "failed.");
4011 /* Now read the raw data into the buffer and write it */
4012 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4013 &numtowrite);
4014 if (!NT_STATUS_IS_OK(status)) {
4015 exit_server_cleanly("secondary writebraw failed");
4018 /* Set up outbuf to return the correct size */
4019 reply_outbuf(req, 1, 0);
4021 if (numtowrite != 0) {
4023 if (numtowrite > 0xFFFF) {
4024 DEBUG(0,("reply_writebraw: Oversize secondary write "
4025 "raw requested (%u). Terminating\n",
4026 (unsigned int)numtowrite ));
4027 exit_server_cleanly("secondary writebraw failed");
4030 if (tcount > nwritten+numtowrite) {
4031 DEBUG(3,("reply_writebraw: Client overestimated the "
4032 "write %d %d %d\n",
4033 (int)tcount,(int)nwritten,(int)numtowrite));
4036 status = read_data(req->sconn->sock, buf+4, numtowrite);
4038 if (!NT_STATUS_IS_OK(status)) {
4039 char addr[INET6_ADDRSTRLEN];
4040 /* Try and give an error message
4041 * saying what client failed. */
4042 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4043 "raw read failed (%s) for client %s. "
4044 "Terminating\n", nt_errstr(status),
4045 get_peer_addr(req->sconn->sock, addr,
4046 sizeof(addr))));
4047 exit_server_cleanly("secondary writebraw failed");
4050 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4051 if (nwritten == -1) {
4052 TALLOC_FREE(buf);
4053 reply_nterror(req, map_nt_error_from_unix(errno));
4054 error_to_writebrawerr(req);
4055 goto strict_unlock;
4058 if (nwritten < (ssize_t)numtowrite) {
4059 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4060 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4063 if (nwritten > 0) {
4064 total_written += nwritten;
4068 TALLOC_FREE(buf);
4069 SSVAL(req->outbuf,smb_vwv0,total_written);
4071 status = sync_file(conn, fsp, write_through);
4072 if (!NT_STATUS_IS_OK(status)) {
4073 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4074 fsp_str_dbg(fsp), nt_errstr(status)));
4075 reply_nterror(req, status);
4076 error_to_writebrawerr(req);
4077 goto strict_unlock;
4080 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4081 "wrote=%d\n",
4082 fsp->fnum, (double)startpos, (int)numtowrite,
4083 (int)total_written));
4085 if (!fsp->print_file) {
4086 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4089 /* We won't return a status if write through is not selected - this
4090 * follows what WfWg does */
4091 END_PROFILE(SMBwritebraw);
4093 if (!write_through && total_written==tcount) {
4095 #if RABBIT_PELLET_FIX
4097 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4098 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4099 * JRA.
4101 if (!send_keepalive(req->sconn->sock)) {
4102 exit_server_cleanly("reply_writebraw: send of "
4103 "keepalive failed");
4105 #endif
4106 TALLOC_FREE(req->outbuf);
4108 return;
4110 strict_unlock:
4111 if (!fsp->print_file) {
4112 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4115 END_PROFILE(SMBwritebraw);
4116 return;
4119 #undef DBGC_CLASS
4120 #define DBGC_CLASS DBGC_LOCKING
4122 /****************************************************************************
4123 Reply to a writeunlock (core+).
4124 ****************************************************************************/
4126 void reply_writeunlock(struct smb_request *req)
4128 connection_struct *conn = req->conn;
4129 ssize_t nwritten = -1;
4130 size_t numtowrite;
4131 off_t startpos;
4132 const char *data;
4133 NTSTATUS status = NT_STATUS_OK;
4134 files_struct *fsp;
4135 struct lock_struct lock;
4136 int saved_errno = 0;
4138 START_PROFILE(SMBwriteunlock);
4140 if (req->wct < 5) {
4141 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4142 END_PROFILE(SMBwriteunlock);
4143 return;
4146 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4148 if (!check_fsp(conn, req, fsp)) {
4149 END_PROFILE(SMBwriteunlock);
4150 return;
4153 if (!CHECK_WRITE(fsp)) {
4154 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4155 END_PROFILE(SMBwriteunlock);
4156 return;
4159 numtowrite = SVAL(req->vwv+1, 0);
4160 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4161 data = (const char *)req->buf + 3;
4163 if (!fsp->print_file && numtowrite > 0) {
4164 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4165 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4166 &lock);
4168 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4169 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4170 END_PROFILE(SMBwriteunlock);
4171 return;
4175 /* The special X/Open SMB protocol handling of
4176 zero length writes is *NOT* done for
4177 this call */
4178 if(numtowrite == 0) {
4179 nwritten = 0;
4180 } else {
4181 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4182 saved_errno = errno;
4185 status = sync_file(conn, fsp, False /* write through */);
4186 if (!NT_STATUS_IS_OK(status)) {
4187 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4188 fsp_str_dbg(fsp), nt_errstr(status)));
4189 reply_nterror(req, status);
4190 goto strict_unlock;
4193 if(nwritten < 0) {
4194 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4195 goto strict_unlock;
4198 if((nwritten < numtowrite) && (numtowrite != 0)) {
4199 reply_nterror(req, NT_STATUS_DISK_FULL);
4200 goto strict_unlock;
4203 if (numtowrite && !fsp->print_file) {
4204 status = do_unlock(req->sconn->msg_ctx,
4205 fsp,
4206 (uint64_t)req->smbpid,
4207 (uint64_t)numtowrite,
4208 (uint64_t)startpos,
4209 WINDOWS_LOCK);
4211 if (NT_STATUS_V(status)) {
4212 reply_nterror(req, status);
4213 goto strict_unlock;
4217 reply_outbuf(req, 1, 0);
4219 SSVAL(req->outbuf,smb_vwv0,nwritten);
4221 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4222 fsp->fnum, (int)numtowrite, (int)nwritten));
4224 strict_unlock:
4225 if (numtowrite && !fsp->print_file) {
4226 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4229 END_PROFILE(SMBwriteunlock);
4230 return;
4233 #undef DBGC_CLASS
4234 #define DBGC_CLASS DBGC_ALL
4236 /****************************************************************************
4237 Reply to a write.
4238 ****************************************************************************/
4240 void reply_write(struct smb_request *req)
4242 connection_struct *conn = req->conn;
4243 size_t numtowrite;
4244 ssize_t nwritten = -1;
4245 off_t startpos;
4246 const char *data;
4247 files_struct *fsp;
4248 struct lock_struct lock;
4249 NTSTATUS status;
4250 int saved_errno = 0;
4252 START_PROFILE(SMBwrite);
4254 if (req->wct < 5) {
4255 END_PROFILE(SMBwrite);
4256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4257 return;
4260 /* If it's an IPC, pass off the pipe handler. */
4261 if (IS_IPC(conn)) {
4262 reply_pipe_write(req);
4263 END_PROFILE(SMBwrite);
4264 return;
4267 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4269 if (!check_fsp(conn, req, fsp)) {
4270 END_PROFILE(SMBwrite);
4271 return;
4274 if (!CHECK_WRITE(fsp)) {
4275 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4276 END_PROFILE(SMBwrite);
4277 return;
4280 numtowrite = SVAL(req->vwv+1, 0);
4281 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4282 data = (const char *)req->buf + 3;
4284 if (!fsp->print_file) {
4285 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4286 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4287 &lock);
4289 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4290 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4291 END_PROFILE(SMBwrite);
4292 return;
4297 * X/Open SMB protocol says that if smb_vwv1 is
4298 * zero then the file size should be extended or
4299 * truncated to the size given in smb_vwv[2-3].
4302 if(numtowrite == 0) {
4304 * This is actually an allocate call, and set EOF. JRA.
4306 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4307 if (nwritten < 0) {
4308 reply_nterror(req, NT_STATUS_DISK_FULL);
4309 goto strict_unlock;
4311 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4312 if (nwritten < 0) {
4313 reply_nterror(req, NT_STATUS_DISK_FULL);
4314 goto strict_unlock;
4316 trigger_write_time_update_immediate(fsp);
4317 } else {
4318 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4321 status = sync_file(conn, fsp, False);
4322 if (!NT_STATUS_IS_OK(status)) {
4323 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4324 fsp_str_dbg(fsp), nt_errstr(status)));
4325 reply_nterror(req, status);
4326 goto strict_unlock;
4329 if(nwritten < 0) {
4330 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4331 goto strict_unlock;
4334 if((nwritten == 0) && (numtowrite != 0)) {
4335 reply_nterror(req, NT_STATUS_DISK_FULL);
4336 goto strict_unlock;
4339 reply_outbuf(req, 1, 0);
4341 SSVAL(req->outbuf,smb_vwv0,nwritten);
4343 if (nwritten < (ssize_t)numtowrite) {
4344 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4345 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4348 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4350 strict_unlock:
4351 if (!fsp->print_file) {
4352 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4355 END_PROFILE(SMBwrite);
4356 return;
4359 /****************************************************************************
4360 Ensure a buffer is a valid writeX for recvfile purposes.
4361 ****************************************************************************/
4363 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4364 (2*14) + /* word count (including bcc) */ \
4365 1 /* pad byte */)
4367 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4368 const uint8_t *inbuf)
4370 size_t numtowrite;
4371 connection_struct *conn = NULL;
4372 unsigned int doff = 0;
4373 size_t len = smb_len_large(inbuf);
4375 if (is_encrypted_packet(sconn, inbuf)) {
4376 /* Can't do this on encrypted
4377 * connections. */
4378 return false;
4381 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4382 return false;
4385 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4386 CVAL(inbuf,smb_wct) != 14) {
4387 DEBUG(10,("is_valid_writeX_buffer: chained or "
4388 "invalid word length.\n"));
4389 return false;
4392 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4393 if (conn == NULL) {
4394 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4395 return false;
4397 if (IS_IPC(conn)) {
4398 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4399 return false;
4401 if (IS_PRINT(conn)) {
4402 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4403 return false;
4405 doff = SVAL(inbuf,smb_vwv11);
4407 numtowrite = SVAL(inbuf,smb_vwv10);
4409 if (len > doff && len - doff > 0xFFFF) {
4410 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4413 if (numtowrite == 0) {
4414 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4415 return false;
4418 /* Ensure the sizes match up. */
4419 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4420 /* no pad byte...old smbclient :-( */
4421 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4422 (unsigned int)doff,
4423 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4424 return false;
4427 if (len - doff != numtowrite) {
4428 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4429 "len = %u, doff = %u, numtowrite = %u\n",
4430 (unsigned int)len,
4431 (unsigned int)doff,
4432 (unsigned int)numtowrite ));
4433 return false;
4436 DEBUG(10,("is_valid_writeX_buffer: true "
4437 "len = %u, doff = %u, numtowrite = %u\n",
4438 (unsigned int)len,
4439 (unsigned int)doff,
4440 (unsigned int)numtowrite ));
4442 return true;
4445 /****************************************************************************
4446 Reply to a write and X.
4447 ****************************************************************************/
4449 void reply_write_and_X(struct smb_request *req)
4451 connection_struct *conn = req->conn;
4452 files_struct *fsp;
4453 struct lock_struct lock;
4454 off_t startpos;
4455 size_t numtowrite;
4456 bool write_through;
4457 ssize_t nwritten;
4458 unsigned int smb_doff;
4459 unsigned int smblen;
4460 const char *data;
4461 NTSTATUS status;
4462 int saved_errno = 0;
4464 START_PROFILE(SMBwriteX);
4466 if ((req->wct != 12) && (req->wct != 14)) {
4467 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4468 goto out;
4471 numtowrite = SVAL(req->vwv+10, 0);
4472 smb_doff = SVAL(req->vwv+11, 0);
4473 smblen = smb_len(req->inbuf);
4475 if (req->unread_bytes > 0xFFFF ||
4476 (smblen > smb_doff &&
4477 smblen - smb_doff > 0xFFFF)) {
4478 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4481 if (req->unread_bytes) {
4482 /* Can't do a recvfile write on IPC$ */
4483 if (IS_IPC(conn)) {
4484 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4485 goto out;
4487 if (numtowrite != req->unread_bytes) {
4488 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4489 goto out;
4491 } else {
4492 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4493 smb_doff + numtowrite > smblen) {
4494 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4495 goto out;
4499 /* If it's an IPC, pass off the pipe handler. */
4500 if (IS_IPC(conn)) {
4501 if (req->unread_bytes) {
4502 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4503 goto out;
4505 reply_pipe_write_and_X(req);
4506 goto out;
4509 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4510 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4511 write_through = BITSETW(req->vwv+7,0);
4513 if (!check_fsp(conn, req, fsp)) {
4514 goto out;
4517 if (!CHECK_WRITE(fsp)) {
4518 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4519 goto out;
4522 data = smb_base(req->inbuf) + smb_doff;
4524 if(req->wct == 14) {
4526 * This is a large offset (64 bit) write.
4528 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4532 /* X/Open SMB protocol says that, unlike SMBwrite
4533 if the length is zero then NO truncation is
4534 done, just a write of zero. To truncate a file,
4535 use SMBwrite. */
4537 if(numtowrite == 0) {
4538 nwritten = 0;
4539 } else {
4540 if (req->unread_bytes == 0) {
4541 status = schedule_aio_write_and_X(conn,
4542 req,
4543 fsp,
4544 data,
4545 startpos,
4546 numtowrite);
4548 if (NT_STATUS_IS_OK(status)) {
4549 /* write scheduled - we're done. */
4550 goto out;
4552 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4553 /* Real error - report to client. */
4554 reply_nterror(req, status);
4555 goto out;
4557 /* NT_STATUS_RETRY - fall through to sync write. */
4560 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4561 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4562 &lock);
4564 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4565 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4566 goto out;
4569 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4570 saved_errno = errno;
4572 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4575 if(nwritten < 0) {
4576 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4577 goto out;
4580 if((nwritten == 0) && (numtowrite != 0)) {
4581 reply_nterror(req, NT_STATUS_DISK_FULL);
4582 goto out;
4585 reply_outbuf(req, 6, 0);
4586 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4587 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4588 SSVAL(req->outbuf,smb_vwv2,nwritten);
4589 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4591 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4592 fsp->fnum, (int)numtowrite, (int)nwritten));
4594 status = sync_file(conn, fsp, write_through);
4595 if (!NT_STATUS_IS_OK(status)) {
4596 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4597 fsp_str_dbg(fsp), nt_errstr(status)));
4598 reply_nterror(req, status);
4599 goto out;
4602 END_PROFILE(SMBwriteX);
4603 return;
4605 out:
4606 if (req->unread_bytes) {
4607 /* writeX failed. drain socket. */
4608 if (drain_socket(req->sconn->sock, req->unread_bytes) !=
4609 req->unread_bytes) {
4610 smb_panic("failed to drain pending bytes");
4612 req->unread_bytes = 0;
4615 END_PROFILE(SMBwriteX);
4616 return;
4619 /****************************************************************************
4620 Reply to a lseek.
4621 ****************************************************************************/
4623 void reply_lseek(struct smb_request *req)
4625 connection_struct *conn = req->conn;
4626 off_t startpos;
4627 off_t res= -1;
4628 int mode,umode;
4629 files_struct *fsp;
4631 START_PROFILE(SMBlseek);
4633 if (req->wct < 4) {
4634 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4635 END_PROFILE(SMBlseek);
4636 return;
4639 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4641 if (!check_fsp(conn, req, fsp)) {
4642 return;
4645 flush_write_cache(fsp, SEEK_FLUSH);
4647 mode = SVAL(req->vwv+1, 0) & 3;
4648 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4649 startpos = (off_t)IVALS(req->vwv+2, 0);
4651 switch (mode) {
4652 case 0:
4653 umode = SEEK_SET;
4654 res = startpos;
4655 break;
4656 case 1:
4657 umode = SEEK_CUR;
4658 res = fsp->fh->pos + startpos;
4659 break;
4660 case 2:
4661 umode = SEEK_END;
4662 break;
4663 default:
4664 umode = SEEK_SET;
4665 res = startpos;
4666 break;
4669 if (umode == SEEK_END) {
4670 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4671 if(errno == EINVAL) {
4672 off_t current_pos = startpos;
4674 if(fsp_stat(fsp) == -1) {
4675 reply_nterror(req,
4676 map_nt_error_from_unix(errno));
4677 END_PROFILE(SMBlseek);
4678 return;
4681 current_pos += fsp->fsp_name->st.st_ex_size;
4682 if(current_pos < 0)
4683 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4687 if(res == -1) {
4688 reply_nterror(req, map_nt_error_from_unix(errno));
4689 END_PROFILE(SMBlseek);
4690 return;
4694 fsp->fh->pos = res;
4696 reply_outbuf(req, 2, 0);
4697 SIVAL(req->outbuf,smb_vwv0,res);
4699 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4700 fsp->fnum, (double)startpos, (double)res, mode));
4702 END_PROFILE(SMBlseek);
4703 return;
4706 /****************************************************************************
4707 Reply to a flush.
4708 ****************************************************************************/
4710 void reply_flush(struct smb_request *req)
4712 connection_struct *conn = req->conn;
4713 uint16 fnum;
4714 files_struct *fsp;
4716 START_PROFILE(SMBflush);
4718 if (req->wct < 1) {
4719 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4720 return;
4723 fnum = SVAL(req->vwv+0, 0);
4724 fsp = file_fsp(req, fnum);
4726 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4727 return;
4730 if (!fsp) {
4731 file_sync_all(conn);
4732 } else {
4733 NTSTATUS status = sync_file(conn, fsp, True);
4734 if (!NT_STATUS_IS_OK(status)) {
4735 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4736 fsp_str_dbg(fsp), nt_errstr(status)));
4737 reply_nterror(req, status);
4738 END_PROFILE(SMBflush);
4739 return;
4743 reply_outbuf(req, 0, 0);
4745 DEBUG(3,("flush\n"));
4746 END_PROFILE(SMBflush);
4747 return;
4750 /****************************************************************************
4751 Reply to a exit.
4752 conn POINTER CAN BE NULL HERE !
4753 ****************************************************************************/
4755 void reply_exit(struct smb_request *req)
4757 START_PROFILE(SMBexit);
4759 file_close_pid(req->sconn, req->smbpid, req->vuid);
4761 reply_outbuf(req, 0, 0);
4763 DEBUG(3,("exit\n"));
4765 END_PROFILE(SMBexit);
4766 return;
4769 /****************************************************************************
4770 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4771 ****************************************************************************/
4773 void reply_close(struct smb_request *req)
4775 connection_struct *conn = req->conn;
4776 NTSTATUS status = NT_STATUS_OK;
4777 files_struct *fsp = NULL;
4778 START_PROFILE(SMBclose);
4780 if (req->wct < 3) {
4781 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4782 END_PROFILE(SMBclose);
4783 return;
4786 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4789 * We can only use check_fsp if we know it's not a directory.
4792 if (!check_fsp_open(conn, req, fsp)) {
4793 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4794 END_PROFILE(SMBclose);
4795 return;
4798 if(fsp->is_directory) {
4800 * Special case - close NT SMB directory handle.
4802 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4803 status = close_file(req, fsp, NORMAL_CLOSE);
4804 } else {
4805 time_t t;
4807 * Close ordinary file.
4810 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4811 fsp->fh->fd, fsp->fnum,
4812 conn->num_files_open));
4815 * Take care of any time sent in the close.
4818 t = srv_make_unix_date3(req->vwv+1);
4819 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4822 * close_file() returns the unix errno if an error
4823 * was detected on close - normally this is due to
4824 * a disk full error. If not then it was probably an I/O error.
4827 status = close_file(req, fsp, NORMAL_CLOSE);
4830 if (!NT_STATUS_IS_OK(status)) {
4831 reply_nterror(req, status);
4832 END_PROFILE(SMBclose);
4833 return;
4836 reply_outbuf(req, 0, 0);
4837 END_PROFILE(SMBclose);
4838 return;
4841 /****************************************************************************
4842 Reply to a writeclose (Core+ protocol).
4843 ****************************************************************************/
4845 void reply_writeclose(struct smb_request *req)
4847 connection_struct *conn = req->conn;
4848 size_t numtowrite;
4849 ssize_t nwritten = -1;
4850 NTSTATUS close_status = NT_STATUS_OK;
4851 off_t startpos;
4852 const char *data;
4853 struct timespec mtime;
4854 files_struct *fsp;
4855 struct lock_struct lock;
4857 START_PROFILE(SMBwriteclose);
4859 if (req->wct < 6) {
4860 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4861 END_PROFILE(SMBwriteclose);
4862 return;
4865 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4867 if (!check_fsp(conn, req, fsp)) {
4868 END_PROFILE(SMBwriteclose);
4869 return;
4871 if (!CHECK_WRITE(fsp)) {
4872 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4873 END_PROFILE(SMBwriteclose);
4874 return;
4877 numtowrite = SVAL(req->vwv+1, 0);
4878 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4879 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4880 data = (const char *)req->buf + 1;
4882 if (!fsp->print_file) {
4883 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4884 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4885 &lock);
4887 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4888 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4889 END_PROFILE(SMBwriteclose);
4890 return;
4894 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4896 set_close_write_time(fsp, mtime);
4899 * More insanity. W2K only closes the file if writelen > 0.
4900 * JRA.
4903 if (numtowrite) {
4904 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4905 "file %s\n", fsp_str_dbg(fsp)));
4906 close_status = close_file(req, fsp, NORMAL_CLOSE);
4909 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4910 fsp->fnum, (int)numtowrite, (int)nwritten,
4911 conn->num_files_open));
4913 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4914 reply_nterror(req, NT_STATUS_DISK_FULL);
4915 goto strict_unlock;
4918 if(!NT_STATUS_IS_OK(close_status)) {
4919 reply_nterror(req, close_status);
4920 goto strict_unlock;
4923 reply_outbuf(req, 1, 0);
4925 SSVAL(req->outbuf,smb_vwv0,nwritten);
4927 strict_unlock:
4928 if (numtowrite && !fsp->print_file) {
4929 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4932 END_PROFILE(SMBwriteclose);
4933 return;
4936 #undef DBGC_CLASS
4937 #define DBGC_CLASS DBGC_LOCKING
4939 /****************************************************************************
4940 Reply to a lock.
4941 ****************************************************************************/
4943 void reply_lock(struct smb_request *req)
4945 connection_struct *conn = req->conn;
4946 uint64_t count,offset;
4947 NTSTATUS status;
4948 files_struct *fsp;
4949 struct byte_range_lock *br_lck = NULL;
4951 START_PROFILE(SMBlock);
4953 if (req->wct < 5) {
4954 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4955 END_PROFILE(SMBlock);
4956 return;
4959 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4961 if (!check_fsp(conn, req, fsp)) {
4962 END_PROFILE(SMBlock);
4963 return;
4966 count = (uint64_t)IVAL(req->vwv+1, 0);
4967 offset = (uint64_t)IVAL(req->vwv+3, 0);
4969 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4970 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4972 br_lck = do_lock(req->sconn->msg_ctx,
4973 fsp,
4974 (uint64_t)req->smbpid,
4975 count,
4976 offset,
4977 WRITE_LOCK,
4978 WINDOWS_LOCK,
4979 False, /* Non-blocking lock. */
4980 &status,
4981 NULL,
4982 NULL);
4984 TALLOC_FREE(br_lck);
4986 if (NT_STATUS_V(status)) {
4987 reply_nterror(req, status);
4988 END_PROFILE(SMBlock);
4989 return;
4992 reply_outbuf(req, 0, 0);
4994 END_PROFILE(SMBlock);
4995 return;
4998 /****************************************************************************
4999 Reply to a unlock.
5000 ****************************************************************************/
5002 void reply_unlock(struct smb_request *req)
5004 connection_struct *conn = req->conn;
5005 uint64_t count,offset;
5006 NTSTATUS status;
5007 files_struct *fsp;
5009 START_PROFILE(SMBunlock);
5011 if (req->wct < 5) {
5012 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5013 END_PROFILE(SMBunlock);
5014 return;
5017 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5019 if (!check_fsp(conn, req, fsp)) {
5020 END_PROFILE(SMBunlock);
5021 return;
5024 count = (uint64_t)IVAL(req->vwv+1, 0);
5025 offset = (uint64_t)IVAL(req->vwv+3, 0);
5027 status = do_unlock(req->sconn->msg_ctx,
5028 fsp,
5029 (uint64_t)req->smbpid,
5030 count,
5031 offset,
5032 WINDOWS_LOCK);
5034 if (NT_STATUS_V(status)) {
5035 reply_nterror(req, status);
5036 END_PROFILE(SMBunlock);
5037 return;
5040 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5041 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5043 reply_outbuf(req, 0, 0);
5045 END_PROFILE(SMBunlock);
5046 return;
5049 #undef DBGC_CLASS
5050 #define DBGC_CLASS DBGC_ALL
5052 /****************************************************************************
5053 Reply to a tdis.
5054 conn POINTER CAN BE NULL HERE !
5055 ****************************************************************************/
5057 void reply_tdis(struct smb_request *req)
5059 connection_struct *conn = req->conn;
5060 START_PROFILE(SMBtdis);
5062 if (!conn) {
5063 DEBUG(4,("Invalid connection in tdis\n"));
5064 reply_force_doserror(req, ERRSRV, ERRinvnid);
5065 END_PROFILE(SMBtdis);
5066 return;
5069 close_cnum(conn,req->vuid);
5070 req->conn = NULL;
5072 reply_outbuf(req, 0, 0);
5073 END_PROFILE(SMBtdis);
5074 return;
5077 /****************************************************************************
5078 Reply to a echo.
5079 conn POINTER CAN BE NULL HERE !
5080 ****************************************************************************/
5082 void reply_echo(struct smb_request *req)
5084 connection_struct *conn = req->conn;
5085 struct smb_perfcount_data local_pcd;
5086 struct smb_perfcount_data *cur_pcd;
5087 int smb_reverb;
5088 int seq_num;
5090 START_PROFILE(SMBecho);
5092 smb_init_perfcount_data(&local_pcd);
5094 if (req->wct < 1) {
5095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5096 END_PROFILE(SMBecho);
5097 return;
5100 smb_reverb = SVAL(req->vwv+0, 0);
5102 reply_outbuf(req, 1, req->buflen);
5104 /* copy any incoming data back out */
5105 if (req->buflen > 0) {
5106 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5109 if (smb_reverb > 100) {
5110 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5111 smb_reverb = 100;
5114 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5116 /* this makes sure we catch the request pcd */
5117 if (seq_num == smb_reverb) {
5118 cur_pcd = &req->pcd;
5119 } else {
5120 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5121 cur_pcd = &local_pcd;
5124 SSVAL(req->outbuf,smb_vwv0,seq_num);
5126 show_msg((char *)req->outbuf);
5127 if (!srv_send_smb(req->sconn,
5128 (char *)req->outbuf,
5129 true, req->seqnum+1,
5130 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5131 cur_pcd))
5132 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5135 DEBUG(3,("echo %d times\n", smb_reverb));
5137 TALLOC_FREE(req->outbuf);
5139 END_PROFILE(SMBecho);
5140 return;
5143 /****************************************************************************
5144 Reply to a printopen.
5145 ****************************************************************************/
5147 void reply_printopen(struct smb_request *req)
5149 connection_struct *conn = req->conn;
5150 files_struct *fsp;
5151 NTSTATUS status;
5153 START_PROFILE(SMBsplopen);
5155 if (req->wct < 2) {
5156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5157 END_PROFILE(SMBsplopen);
5158 return;
5161 if (!CAN_PRINT(conn)) {
5162 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5163 END_PROFILE(SMBsplopen);
5164 return;
5167 status = file_new(req, conn, &fsp);
5168 if(!NT_STATUS_IS_OK(status)) {
5169 reply_nterror(req, status);
5170 END_PROFILE(SMBsplopen);
5171 return;
5174 /* Open for exclusive use, write only. */
5175 status = print_spool_open(fsp, NULL, req->vuid);
5177 if (!NT_STATUS_IS_OK(status)) {
5178 file_free(req, fsp);
5179 reply_nterror(req, status);
5180 END_PROFILE(SMBsplopen);
5181 return;
5184 reply_outbuf(req, 1, 0);
5185 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5187 DEBUG(3,("openprint fd=%d fnum=%d\n",
5188 fsp->fh->fd, fsp->fnum));
5190 END_PROFILE(SMBsplopen);
5191 return;
5194 /****************************************************************************
5195 Reply to a printclose.
5196 ****************************************************************************/
5198 void reply_printclose(struct smb_request *req)
5200 connection_struct *conn = req->conn;
5201 files_struct *fsp;
5202 NTSTATUS status;
5204 START_PROFILE(SMBsplclose);
5206 if (req->wct < 1) {
5207 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5208 END_PROFILE(SMBsplclose);
5209 return;
5212 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5214 if (!check_fsp(conn, req, fsp)) {
5215 END_PROFILE(SMBsplclose);
5216 return;
5219 if (!CAN_PRINT(conn)) {
5220 reply_force_doserror(req, ERRSRV, ERRerror);
5221 END_PROFILE(SMBsplclose);
5222 return;
5225 DEBUG(3,("printclose fd=%d fnum=%d\n",
5226 fsp->fh->fd,fsp->fnum));
5228 status = close_file(req, fsp, NORMAL_CLOSE);
5230 if(!NT_STATUS_IS_OK(status)) {
5231 reply_nterror(req, status);
5232 END_PROFILE(SMBsplclose);
5233 return;
5236 reply_outbuf(req, 0, 0);
5238 END_PROFILE(SMBsplclose);
5239 return;
5242 /****************************************************************************
5243 Reply to a printqueue.
5244 ****************************************************************************/
5246 void reply_printqueue(struct smb_request *req)
5248 connection_struct *conn = req->conn;
5249 int max_count;
5250 int start_index;
5252 START_PROFILE(SMBsplretq);
5254 if (req->wct < 2) {
5255 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5256 END_PROFILE(SMBsplretq);
5257 return;
5260 max_count = SVAL(req->vwv+0, 0);
5261 start_index = SVAL(req->vwv+1, 0);
5263 /* we used to allow the client to get the cnum wrong, but that
5264 is really quite gross and only worked when there was only
5265 one printer - I think we should now only accept it if they
5266 get it right (tridge) */
5267 if (!CAN_PRINT(conn)) {
5268 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5269 END_PROFILE(SMBsplretq);
5270 return;
5273 reply_outbuf(req, 2, 3);
5274 SSVAL(req->outbuf,smb_vwv0,0);
5275 SSVAL(req->outbuf,smb_vwv1,0);
5276 SCVAL(smb_buf(req->outbuf),0,1);
5277 SSVAL(smb_buf(req->outbuf),1,0);
5279 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5280 start_index, max_count));
5283 TALLOC_CTX *mem_ctx = talloc_tos();
5284 NTSTATUS status;
5285 WERROR werr;
5286 const char *sharename = lp_servicename(SNUM(conn));
5287 struct rpc_pipe_client *cli = NULL;
5288 struct dcerpc_binding_handle *b = NULL;
5289 struct policy_handle handle;
5290 struct spoolss_DevmodeContainer devmode_ctr;
5291 union spoolss_JobInfo *info;
5292 uint32_t count;
5293 uint32_t num_to_get;
5294 uint32_t first;
5295 uint32_t i;
5297 ZERO_STRUCT(handle);
5299 status = rpc_pipe_open_interface(conn,
5300 &ndr_table_spoolss.syntax_id,
5301 conn->session_info,
5302 conn->sconn->remote_address,
5303 conn->sconn->msg_ctx,
5304 &cli);
5305 if (!NT_STATUS_IS_OK(status)) {
5306 DEBUG(0, ("reply_printqueue: "
5307 "could not connect to spoolss: %s\n",
5308 nt_errstr(status)));
5309 reply_nterror(req, status);
5310 goto out;
5312 b = cli->binding_handle;
5314 ZERO_STRUCT(devmode_ctr);
5316 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5317 sharename,
5318 NULL, devmode_ctr,
5319 SEC_FLAG_MAXIMUM_ALLOWED,
5320 &handle,
5321 &werr);
5322 if (!NT_STATUS_IS_OK(status)) {
5323 reply_nterror(req, status);
5324 goto out;
5326 if (!W_ERROR_IS_OK(werr)) {
5327 reply_nterror(req, werror_to_ntstatus(werr));
5328 goto out;
5331 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5332 &handle,
5333 0, /* firstjob */
5334 0xff, /* numjobs */
5335 2, /* level */
5336 0, /* offered */
5337 &count,
5338 &info);
5339 if (!W_ERROR_IS_OK(werr)) {
5340 reply_nterror(req, werror_to_ntstatus(werr));
5341 goto out;
5344 if (max_count > 0) {
5345 first = start_index;
5346 } else {
5347 first = start_index + max_count + 1;
5350 if (first >= count) {
5351 num_to_get = first;
5352 } else {
5353 num_to_get = first + MIN(ABS(max_count), count - first);
5356 for (i = first; i < num_to_get; i++) {
5357 char blob[28];
5358 char *p = blob;
5359 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5360 int qstatus;
5361 uint16_t qrapjobid = pjobid_to_rap(sharename,
5362 info[i].info2.job_id);
5364 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5365 qstatus = 2;
5366 } else {
5367 qstatus = 3;
5370 srv_put_dos_date2(p, 0, qtime);
5371 SCVAL(p, 4, qstatus);
5372 SSVAL(p, 5, qrapjobid);
5373 SIVAL(p, 7, info[i].info2.size);
5374 SCVAL(p, 11, 0);
5375 srvstr_push(blob, req->flags2, p+12,
5376 info[i].info2.notify_name, 16, STR_ASCII);
5378 if (message_push_blob(
5379 &req->outbuf,
5380 data_blob_const(
5381 blob, sizeof(blob))) == -1) {
5382 reply_nterror(req, NT_STATUS_NO_MEMORY);
5383 goto out;
5387 if (count > 0) {
5388 SSVAL(req->outbuf,smb_vwv0,count);
5389 SSVAL(req->outbuf,smb_vwv1,
5390 (max_count>0?first+count:first-1));
5391 SCVAL(smb_buf(req->outbuf),0,1);
5392 SSVAL(smb_buf(req->outbuf),1,28*count);
5396 DEBUG(3, ("%u entries returned in queue\n",
5397 (unsigned)count));
5399 out:
5400 if (b && is_valid_policy_hnd(&handle)) {
5401 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5406 END_PROFILE(SMBsplretq);
5407 return;
5410 /****************************************************************************
5411 Reply to a printwrite.
5412 ****************************************************************************/
5414 void reply_printwrite(struct smb_request *req)
5416 connection_struct *conn = req->conn;
5417 int numtowrite;
5418 const char *data;
5419 files_struct *fsp;
5421 START_PROFILE(SMBsplwr);
5423 if (req->wct < 1) {
5424 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5425 END_PROFILE(SMBsplwr);
5426 return;
5429 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5431 if (!check_fsp(conn, req, fsp)) {
5432 END_PROFILE(SMBsplwr);
5433 return;
5436 if (!fsp->print_file) {
5437 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5438 END_PROFILE(SMBsplwr);
5439 return;
5442 if (!CHECK_WRITE(fsp)) {
5443 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5444 END_PROFILE(SMBsplwr);
5445 return;
5448 numtowrite = SVAL(req->buf, 1);
5450 if (req->buflen < numtowrite + 3) {
5451 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5452 END_PROFILE(SMBsplwr);
5453 return;
5456 data = (const char *)req->buf + 3;
5458 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5459 reply_nterror(req, map_nt_error_from_unix(errno));
5460 END_PROFILE(SMBsplwr);
5461 return;
5464 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5466 END_PROFILE(SMBsplwr);
5467 return;
5470 /****************************************************************************
5471 Reply to a mkdir.
5472 ****************************************************************************/
5474 void reply_mkdir(struct smb_request *req)
5476 connection_struct *conn = req->conn;
5477 struct smb_filename *smb_dname = NULL;
5478 char *directory = NULL;
5479 NTSTATUS status;
5480 TALLOC_CTX *ctx = talloc_tos();
5482 START_PROFILE(SMBmkdir);
5484 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5485 STR_TERMINATE, &status);
5486 if (!NT_STATUS_IS_OK(status)) {
5487 reply_nterror(req, status);
5488 goto out;
5491 status = filename_convert(ctx, conn,
5492 req->flags2 & FLAGS2_DFS_PATHNAMES,
5493 directory,
5495 NULL,
5496 &smb_dname);
5497 if (!NT_STATUS_IS_OK(status)) {
5498 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5499 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5500 ERRSRV, ERRbadpath);
5501 goto out;
5503 reply_nterror(req, status);
5504 goto out;
5507 status = create_directory(conn, req, smb_dname);
5509 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5511 if (!NT_STATUS_IS_OK(status)) {
5513 if (!use_nt_status()
5514 && NT_STATUS_EQUAL(status,
5515 NT_STATUS_OBJECT_NAME_COLLISION)) {
5517 * Yes, in the DOS error code case we get a
5518 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5519 * samba4 torture test.
5521 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5524 reply_nterror(req, status);
5525 goto out;
5528 reply_outbuf(req, 0, 0);
5530 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5531 out:
5532 TALLOC_FREE(smb_dname);
5533 END_PROFILE(SMBmkdir);
5534 return;
5537 /****************************************************************************
5538 Reply to a rmdir.
5539 ****************************************************************************/
5541 void reply_rmdir(struct smb_request *req)
5543 connection_struct *conn = req->conn;
5544 struct smb_filename *smb_dname = NULL;
5545 char *directory = NULL;
5546 NTSTATUS status;
5547 TALLOC_CTX *ctx = talloc_tos();
5548 files_struct *fsp = NULL;
5549 int info = 0;
5550 struct smbd_server_connection *sconn = req->sconn;
5552 START_PROFILE(SMBrmdir);
5554 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5555 STR_TERMINATE, &status);
5556 if (!NT_STATUS_IS_OK(status)) {
5557 reply_nterror(req, status);
5558 goto out;
5561 status = filename_convert(ctx, conn,
5562 req->flags2 & FLAGS2_DFS_PATHNAMES,
5563 directory,
5565 NULL,
5566 &smb_dname);
5567 if (!NT_STATUS_IS_OK(status)) {
5568 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5569 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5570 ERRSRV, ERRbadpath);
5571 goto out;
5573 reply_nterror(req, status);
5574 goto out;
5577 if (is_ntfs_stream_smb_fname(smb_dname)) {
5578 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5579 goto out;
5582 status = SMB_VFS_CREATE_FILE(
5583 conn, /* conn */
5584 req, /* req */
5585 0, /* root_dir_fid */
5586 smb_dname, /* fname */
5587 DELETE_ACCESS, /* access_mask */
5588 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5589 FILE_SHARE_DELETE),
5590 FILE_OPEN, /* create_disposition*/
5591 FILE_DIRECTORY_FILE, /* create_options */
5592 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5593 0, /* oplock_request */
5594 0, /* allocation_size */
5595 0, /* private_flags */
5596 NULL, /* sd */
5597 NULL, /* ea_list */
5598 &fsp, /* result */
5599 &info); /* pinfo */
5601 if (!NT_STATUS_IS_OK(status)) {
5602 if (open_was_deferred(req->sconn, req->mid)) {
5603 /* We have re-scheduled this call. */
5604 goto out;
5606 reply_nterror(req, status);
5607 goto out;
5610 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5611 if (!NT_STATUS_IS_OK(status)) {
5612 close_file(req, fsp, ERROR_CLOSE);
5613 reply_nterror(req, status);
5614 goto out;
5617 if (!set_delete_on_close(fsp, true,
5618 conn->session_info->security_token,
5619 conn->session_info->unix_token)) {
5620 close_file(req, fsp, ERROR_CLOSE);
5621 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5622 goto out;
5625 status = close_file(req, fsp, NORMAL_CLOSE);
5626 if (!NT_STATUS_IS_OK(status)) {
5627 reply_nterror(req, status);
5628 } else {
5629 reply_outbuf(req, 0, 0);
5632 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5634 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5635 out:
5636 TALLOC_FREE(smb_dname);
5637 END_PROFILE(SMBrmdir);
5638 return;
5641 /*******************************************************************
5642 Resolve wildcards in a filename rename.
5643 ********************************************************************/
5645 static bool resolve_wildcards(TALLOC_CTX *ctx,
5646 const char *name1,
5647 const char *name2,
5648 char **pp_newname)
5650 char *name2_copy = NULL;
5651 char *root1 = NULL;
5652 char *root2 = NULL;
5653 char *ext1 = NULL;
5654 char *ext2 = NULL;
5655 char *p,*p2, *pname1, *pname2;
5657 name2_copy = talloc_strdup(ctx, name2);
5658 if (!name2_copy) {
5659 return False;
5662 pname1 = strrchr_m(name1,'/');
5663 pname2 = strrchr_m(name2_copy,'/');
5665 if (!pname1 || !pname2) {
5666 return False;
5669 /* Truncate the copy of name2 at the last '/' */
5670 *pname2 = '\0';
5672 /* Now go past the '/' */
5673 pname1++;
5674 pname2++;
5676 root1 = talloc_strdup(ctx, pname1);
5677 root2 = talloc_strdup(ctx, pname2);
5679 if (!root1 || !root2) {
5680 return False;
5683 p = strrchr_m(root1,'.');
5684 if (p) {
5685 *p = 0;
5686 ext1 = talloc_strdup(ctx, p+1);
5687 } else {
5688 ext1 = talloc_strdup(ctx, "");
5690 p = strrchr_m(root2,'.');
5691 if (p) {
5692 *p = 0;
5693 ext2 = talloc_strdup(ctx, p+1);
5694 } else {
5695 ext2 = talloc_strdup(ctx, "");
5698 if (!ext1 || !ext2) {
5699 return False;
5702 p = root1;
5703 p2 = root2;
5704 while (*p2) {
5705 if (*p2 == '?') {
5706 /* Hmmm. Should this be mb-aware ? */
5707 *p2 = *p;
5708 p2++;
5709 } else if (*p2 == '*') {
5710 *p2 = '\0';
5711 root2 = talloc_asprintf(ctx, "%s%s",
5712 root2,
5714 if (!root2) {
5715 return False;
5717 break;
5718 } else {
5719 p2++;
5721 if (*p) {
5722 p++;
5726 p = ext1;
5727 p2 = ext2;
5728 while (*p2) {
5729 if (*p2 == '?') {
5730 /* Hmmm. Should this be mb-aware ? */
5731 *p2 = *p;
5732 p2++;
5733 } else if (*p2 == '*') {
5734 *p2 = '\0';
5735 ext2 = talloc_asprintf(ctx, "%s%s",
5736 ext2,
5738 if (!ext2) {
5739 return False;
5741 break;
5742 } else {
5743 p2++;
5745 if (*p) {
5746 p++;
5750 if (*ext2) {
5751 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5752 name2_copy,
5753 root2,
5754 ext2);
5755 } else {
5756 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5757 name2_copy,
5758 root2);
5761 if (!*pp_newname) {
5762 return False;
5765 return True;
5768 /****************************************************************************
5769 Ensure open files have their names updated. Updated to notify other smbd's
5770 asynchronously.
5771 ****************************************************************************/
5773 static void rename_open_files(connection_struct *conn,
5774 struct share_mode_lock *lck,
5775 uint32_t orig_name_hash,
5776 const struct smb_filename *smb_fname_dst)
5778 files_struct *fsp;
5779 bool did_rename = False;
5780 NTSTATUS status;
5781 uint32_t new_name_hash = 0;
5783 for(fsp = file_find_di_first(conn->sconn, lck->data->id); fsp;
5784 fsp = file_find_di_next(fsp)) {
5785 /* fsp_name is a relative path under the fsp. To change this for other
5786 sharepaths we need to manipulate relative paths. */
5787 /* TODO - create the absolute path and manipulate the newname
5788 relative to the sharepath. */
5789 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5790 continue;
5792 if (fsp->name_hash != orig_name_hash) {
5793 continue;
5795 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5796 "(file_id %s) from %s -> %s\n", fsp->fnum,
5797 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5798 smb_fname_str_dbg(smb_fname_dst)));
5800 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5801 if (NT_STATUS_IS_OK(status)) {
5802 did_rename = True;
5803 new_name_hash = fsp->name_hash;
5807 if (!did_rename) {
5808 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5809 "for %s\n", file_id_string_tos(&lck->data->id),
5810 smb_fname_str_dbg(smb_fname_dst)));
5813 /* Send messages to all smbd's (not ourself) that the name has changed. */
5814 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5815 orig_name_hash, new_name_hash,
5816 smb_fname_dst);
5820 /****************************************************************************
5821 We need to check if the source path is a parent directory of the destination
5822 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5823 refuse the rename with a sharing violation. Under UNIX the above call can
5824 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5825 probably need to check that the client is a Windows one before disallowing
5826 this as a UNIX client (one with UNIX extensions) can know the source is a
5827 symlink and make this decision intelligently. Found by an excellent bug
5828 report from <AndyLiebman@aol.com>.
5829 ****************************************************************************/
5831 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5832 const struct smb_filename *smb_fname_dst)
5834 const char *psrc = smb_fname_src->base_name;
5835 const char *pdst = smb_fname_dst->base_name;
5836 size_t slen;
5838 if (psrc[0] == '.' && psrc[1] == '/') {
5839 psrc += 2;
5841 if (pdst[0] == '.' && pdst[1] == '/') {
5842 pdst += 2;
5844 if ((slen = strlen(psrc)) > strlen(pdst)) {
5845 return False;
5847 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5851 * Do the notify calls from a rename
5854 static void notify_rename(connection_struct *conn, bool is_dir,
5855 const struct smb_filename *smb_fname_src,
5856 const struct smb_filename *smb_fname_dst)
5858 char *parent_dir_src = NULL;
5859 char *parent_dir_dst = NULL;
5860 uint32 mask;
5862 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5863 : FILE_NOTIFY_CHANGE_FILE_NAME;
5865 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5866 &parent_dir_src, NULL) ||
5867 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5868 &parent_dir_dst, NULL)) {
5869 goto out;
5872 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5873 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5874 smb_fname_src->base_name);
5875 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5876 smb_fname_dst->base_name);
5878 else {
5879 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5880 smb_fname_src->base_name);
5881 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5882 smb_fname_dst->base_name);
5885 /* this is a strange one. w2k3 gives an additional event for
5886 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5887 files, but not directories */
5888 if (!is_dir) {
5889 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5890 FILE_NOTIFY_CHANGE_ATTRIBUTES
5891 |FILE_NOTIFY_CHANGE_CREATION,
5892 smb_fname_dst->base_name);
5894 out:
5895 TALLOC_FREE(parent_dir_src);
5896 TALLOC_FREE(parent_dir_dst);
5899 /****************************************************************************
5900 Returns an error if the parent directory for a filename is open in an
5901 incompatible way.
5902 ****************************************************************************/
5904 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
5905 const struct smb_filename *smb_fname_dst_in)
5907 char *parent_dir = NULL;
5908 struct smb_filename smb_fname_parent;
5909 struct file_id id;
5910 files_struct *fsp = NULL;
5911 int ret;
5913 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
5914 &parent_dir, NULL)) {
5915 return NT_STATUS_NO_MEMORY;
5917 ZERO_STRUCT(smb_fname_parent);
5918 smb_fname_parent.base_name = parent_dir;
5920 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
5921 if (ret == -1) {
5922 return map_nt_error_from_unix(errno);
5926 * We're only checking on this smbd here, mostly good
5927 * enough.. and will pass tests.
5930 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
5931 for (fsp = file_find_di_first(conn->sconn, id); fsp;
5932 fsp = file_find_di_next(fsp)) {
5933 if (fsp->access_mask & DELETE_ACCESS) {
5934 return NT_STATUS_SHARING_VIOLATION;
5937 return NT_STATUS_OK;
5940 /****************************************************************************
5941 Rename an open file - given an fsp.
5942 ****************************************************************************/
5944 NTSTATUS rename_internals_fsp(connection_struct *conn,
5945 files_struct *fsp,
5946 const struct smb_filename *smb_fname_dst_in,
5947 uint32 attrs,
5948 bool replace_if_exists)
5950 TALLOC_CTX *ctx = talloc_tos();
5951 struct smb_filename *smb_fname_dst = NULL;
5952 NTSTATUS status = NT_STATUS_OK;
5953 struct share_mode_lock *lck = NULL;
5954 bool dst_exists, old_is_stream, new_is_stream;
5956 status = check_name(conn, smb_fname_dst_in->base_name);
5957 if (!NT_STATUS_IS_OK(status)) {
5958 return status;
5961 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
5962 if (!NT_STATUS_IS_OK(status)) {
5963 return status;
5966 /* Make a copy of the dst smb_fname structs */
5968 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5969 if (!NT_STATUS_IS_OK(status)) {
5970 goto out;
5974 * Check for special case with case preserving and not
5975 * case sensitive. If the old last component differs from the original
5976 * last component only by case, then we should allow
5977 * the rename (user is trying to change the case of the
5978 * filename).
5980 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5981 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5982 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5983 char *last_slash;
5984 char *fname_dst_lcomp_base_mod = NULL;
5985 struct smb_filename *smb_fname_orig_lcomp = NULL;
5988 * Get the last component of the destination name.
5990 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5991 if (last_slash) {
5992 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5993 } else {
5994 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
5996 if (!fname_dst_lcomp_base_mod) {
5997 status = NT_STATUS_NO_MEMORY;
5998 goto out;
6002 * Create an smb_filename struct using the original last
6003 * component of the destination.
6005 status = create_synthetic_smb_fname_split(ctx,
6006 smb_fname_dst->original_lcomp, NULL,
6007 &smb_fname_orig_lcomp);
6008 if (!NT_STATUS_IS_OK(status)) {
6009 TALLOC_FREE(fname_dst_lcomp_base_mod);
6010 goto out;
6013 /* If the base names only differ by case, use original. */
6014 if(!strcsequal(fname_dst_lcomp_base_mod,
6015 smb_fname_orig_lcomp->base_name)) {
6016 char *tmp;
6018 * Replace the modified last component with the
6019 * original.
6021 if (last_slash) {
6022 *last_slash = '\0'; /* Truncate at the '/' */
6023 tmp = talloc_asprintf(smb_fname_dst,
6024 "%s/%s",
6025 smb_fname_dst->base_name,
6026 smb_fname_orig_lcomp->base_name);
6027 } else {
6028 tmp = talloc_asprintf(smb_fname_dst,
6029 "%s",
6030 smb_fname_orig_lcomp->base_name);
6032 if (tmp == NULL) {
6033 status = NT_STATUS_NO_MEMORY;
6034 TALLOC_FREE(fname_dst_lcomp_base_mod);
6035 TALLOC_FREE(smb_fname_orig_lcomp);
6036 goto out;
6038 TALLOC_FREE(smb_fname_dst->base_name);
6039 smb_fname_dst->base_name = tmp;
6042 /* If the stream_names only differ by case, use original. */
6043 if(!strcsequal(smb_fname_dst->stream_name,
6044 smb_fname_orig_lcomp->stream_name)) {
6045 char *tmp = NULL;
6046 /* Use the original stream. */
6047 tmp = talloc_strdup(smb_fname_dst,
6048 smb_fname_orig_lcomp->stream_name);
6049 if (tmp == NULL) {
6050 status = NT_STATUS_NO_MEMORY;
6051 TALLOC_FREE(fname_dst_lcomp_base_mod);
6052 TALLOC_FREE(smb_fname_orig_lcomp);
6053 goto out;
6055 TALLOC_FREE(smb_fname_dst->stream_name);
6056 smb_fname_dst->stream_name = tmp;
6058 TALLOC_FREE(fname_dst_lcomp_base_mod);
6059 TALLOC_FREE(smb_fname_orig_lcomp);
6063 * If the src and dest names are identical - including case,
6064 * don't do the rename, just return success.
6067 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6068 strcsequal(fsp->fsp_name->stream_name,
6069 smb_fname_dst->stream_name)) {
6070 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6071 "- returning success\n",
6072 smb_fname_str_dbg(smb_fname_dst)));
6073 status = NT_STATUS_OK;
6074 goto out;
6077 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6078 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6080 /* Return the correct error code if both names aren't streams. */
6081 if (!old_is_stream && new_is_stream) {
6082 status = NT_STATUS_OBJECT_NAME_INVALID;
6083 goto out;
6086 if (old_is_stream && !new_is_stream) {
6087 status = NT_STATUS_INVALID_PARAMETER;
6088 goto out;
6091 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6093 if(!replace_if_exists && dst_exists) {
6094 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6095 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6096 smb_fname_str_dbg(smb_fname_dst)));
6097 status = NT_STATUS_OBJECT_NAME_COLLISION;
6098 goto out;
6101 if (dst_exists) {
6102 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6103 &smb_fname_dst->st);
6104 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6105 fileid);
6106 /* The file can be open when renaming a stream */
6107 if (dst_fsp && !new_is_stream) {
6108 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6109 status = NT_STATUS_ACCESS_DENIED;
6110 goto out;
6114 /* Ensure we have a valid stat struct for the source. */
6115 status = vfs_stat_fsp(fsp);
6116 if (!NT_STATUS_IS_OK(status)) {
6117 goto out;
6120 status = can_rename(conn, fsp, attrs);
6122 if (!NT_STATUS_IS_OK(status)) {
6123 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6124 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6125 smb_fname_str_dbg(smb_fname_dst)));
6126 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6127 status = NT_STATUS_ACCESS_DENIED;
6128 goto out;
6131 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6132 status = NT_STATUS_ACCESS_DENIED;
6135 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6138 * We have the file open ourselves, so not being able to get the
6139 * corresponding share mode lock is a fatal error.
6142 SMB_ASSERT(lck != NULL);
6144 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6145 uint32 create_options = fsp->fh->private_options;
6147 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6148 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6149 smb_fname_str_dbg(smb_fname_dst)));
6151 if (!lp_posix_pathnames() &&
6152 (lp_map_archive(SNUM(conn)) ||
6153 lp_store_dos_attributes(SNUM(conn)))) {
6154 /* We must set the archive bit on the newly
6155 renamed file. */
6156 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6157 uint32_t old_dosmode = dos_mode(conn,
6158 smb_fname_dst);
6159 file_set_dosmode(conn,
6160 smb_fname_dst,
6161 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6162 NULL,
6163 true);
6167 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6168 smb_fname_dst);
6170 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6173 * A rename acts as a new file create w.r.t. allowing an initial delete
6174 * on close, probably because in Windows there is a new handle to the
6175 * new file. If initial delete on close was requested but not
6176 * originally set, we need to set it here. This is probably not 100% correct,
6177 * but will work for the CIFSFS client which in non-posix mode
6178 * depends on these semantics. JRA.
6181 if (create_options & FILE_DELETE_ON_CLOSE) {
6182 status = can_set_delete_on_close(fsp, 0);
6184 if (NT_STATUS_IS_OK(status)) {
6185 /* Note that here we set the *inital* delete on close flag,
6186 * not the regular one. The magic gets handled in close. */
6187 fsp->initial_delete_on_close = True;
6190 TALLOC_FREE(lck);
6191 status = NT_STATUS_OK;
6192 goto out;
6195 TALLOC_FREE(lck);
6197 if (errno == ENOTDIR || errno == EISDIR) {
6198 status = NT_STATUS_OBJECT_NAME_COLLISION;
6199 } else {
6200 status = map_nt_error_from_unix(errno);
6203 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6204 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6205 smb_fname_str_dbg(smb_fname_dst)));
6207 out:
6208 TALLOC_FREE(smb_fname_dst);
6210 return status;
6213 /****************************************************************************
6214 The guts of the rename command, split out so it may be called by the NT SMB
6215 code.
6216 ****************************************************************************/
6218 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6219 connection_struct *conn,
6220 struct smb_request *req,
6221 struct smb_filename *smb_fname_src,
6222 struct smb_filename *smb_fname_dst,
6223 uint32 attrs,
6224 bool replace_if_exists,
6225 bool src_has_wild,
6226 bool dest_has_wild,
6227 uint32_t access_mask)
6229 char *fname_src_dir = NULL;
6230 char *fname_src_mask = NULL;
6231 int count=0;
6232 NTSTATUS status = NT_STATUS_OK;
6233 struct smb_Dir *dir_hnd = NULL;
6234 const char *dname = NULL;
6235 char *talloced = NULL;
6236 long offset = 0;
6237 int create_options = 0;
6238 bool posix_pathnames = lp_posix_pathnames();
6241 * Split the old name into directory and last component
6242 * strings. Note that unix_convert may have stripped off a
6243 * leading ./ from both name and newname if the rename is
6244 * at the root of the share. We need to make sure either both
6245 * name and newname contain a / character or neither of them do
6246 * as this is checked in resolve_wildcards().
6249 /* Split up the directory from the filename/mask. */
6250 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6251 &fname_src_dir, &fname_src_mask);
6252 if (!NT_STATUS_IS_OK(status)) {
6253 status = NT_STATUS_NO_MEMORY;
6254 goto out;
6258 * We should only check the mangled cache
6259 * here if unix_convert failed. This means
6260 * that the path in 'mask' doesn't exist
6261 * on the file system and so we need to look
6262 * for a possible mangle. This patch from
6263 * Tine Smukavec <valentin.smukavec@hermes.si>.
6266 if (!VALID_STAT(smb_fname_src->st) &&
6267 mangle_is_mangled(fname_src_mask, conn->params)) {
6268 char *new_mask = NULL;
6269 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6270 conn->params);
6271 if (new_mask) {
6272 TALLOC_FREE(fname_src_mask);
6273 fname_src_mask = new_mask;
6277 if (!src_has_wild) {
6278 files_struct *fsp;
6281 * Only one file needs to be renamed. Append the mask back
6282 * onto the directory.
6284 TALLOC_FREE(smb_fname_src->base_name);
6285 if (ISDOT(fname_src_dir)) {
6286 /* Ensure we use canonical names on open. */
6287 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6288 "%s",
6289 fname_src_mask);
6290 } else {
6291 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6292 "%s/%s",
6293 fname_src_dir,
6294 fname_src_mask);
6296 if (!smb_fname_src->base_name) {
6297 status = NT_STATUS_NO_MEMORY;
6298 goto out;
6301 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6302 "case_preserve = %d, short case preserve = %d, "
6303 "directory = %s, newname = %s, "
6304 "last_component_dest = %s\n",
6305 conn->case_sensitive, conn->case_preserve,
6306 conn->short_case_preserve,
6307 smb_fname_str_dbg(smb_fname_src),
6308 smb_fname_str_dbg(smb_fname_dst),
6309 smb_fname_dst->original_lcomp));
6311 /* The dest name still may have wildcards. */
6312 if (dest_has_wild) {
6313 char *fname_dst_mod = NULL;
6314 if (!resolve_wildcards(smb_fname_dst,
6315 smb_fname_src->base_name,
6316 smb_fname_dst->base_name,
6317 &fname_dst_mod)) {
6318 DEBUG(6, ("rename_internals: resolve_wildcards "
6319 "%s %s failed\n",
6320 smb_fname_src->base_name,
6321 smb_fname_dst->base_name));
6322 status = NT_STATUS_NO_MEMORY;
6323 goto out;
6325 TALLOC_FREE(smb_fname_dst->base_name);
6326 smb_fname_dst->base_name = fname_dst_mod;
6329 ZERO_STRUCT(smb_fname_src->st);
6330 if (posix_pathnames) {
6331 SMB_VFS_LSTAT(conn, smb_fname_src);
6332 } else {
6333 SMB_VFS_STAT(conn, smb_fname_src);
6336 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6337 create_options |= FILE_DIRECTORY_FILE;
6340 status = SMB_VFS_CREATE_FILE(
6341 conn, /* conn */
6342 req, /* req */
6343 0, /* root_dir_fid */
6344 smb_fname_src, /* fname */
6345 access_mask, /* access_mask */
6346 (FILE_SHARE_READ | /* share_access */
6347 FILE_SHARE_WRITE),
6348 FILE_OPEN, /* create_disposition*/
6349 create_options, /* create_options */
6350 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6351 0, /* oplock_request */
6352 0, /* allocation_size */
6353 0, /* private_flags */
6354 NULL, /* sd */
6355 NULL, /* ea_list */
6356 &fsp, /* result */
6357 NULL); /* pinfo */
6359 if (!NT_STATUS_IS_OK(status)) {
6360 DEBUG(3, ("Could not open rename source %s: %s\n",
6361 smb_fname_str_dbg(smb_fname_src),
6362 nt_errstr(status)));
6363 goto out;
6366 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6367 attrs, replace_if_exists);
6369 close_file(req, fsp, NORMAL_CLOSE);
6371 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6372 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6373 smb_fname_str_dbg(smb_fname_dst)));
6375 goto out;
6379 * Wildcards - process each file that matches.
6381 if (strequal(fname_src_mask, "????????.???")) {
6382 TALLOC_FREE(fname_src_mask);
6383 fname_src_mask = talloc_strdup(ctx, "*");
6384 if (!fname_src_mask) {
6385 status = NT_STATUS_NO_MEMORY;
6386 goto out;
6390 status = check_name(conn, fname_src_dir);
6391 if (!NT_STATUS_IS_OK(status)) {
6392 goto out;
6395 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6396 attrs);
6397 if (dir_hnd == NULL) {
6398 status = map_nt_error_from_unix(errno);
6399 goto out;
6402 status = NT_STATUS_NO_SUCH_FILE;
6404 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6405 * - gentest fix. JRA
6408 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6409 &talloced))) {
6410 files_struct *fsp = NULL;
6411 char *destname = NULL;
6412 bool sysdir_entry = False;
6414 /* Quick check for "." and ".." */
6415 if (ISDOT(dname) || ISDOTDOT(dname)) {
6416 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6417 sysdir_entry = True;
6418 } else {
6419 TALLOC_FREE(talloced);
6420 continue;
6424 if (!is_visible_file(conn, fname_src_dir, dname,
6425 &smb_fname_src->st, false)) {
6426 TALLOC_FREE(talloced);
6427 continue;
6430 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6431 TALLOC_FREE(talloced);
6432 continue;
6435 if (sysdir_entry) {
6436 status = NT_STATUS_OBJECT_NAME_INVALID;
6437 break;
6440 TALLOC_FREE(smb_fname_src->base_name);
6441 if (ISDOT(fname_src_dir)) {
6442 /* Ensure we use canonical names on open. */
6443 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6444 "%s",
6445 dname);
6446 } else {
6447 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6448 "%s/%s",
6449 fname_src_dir,
6450 dname);
6452 if (!smb_fname_src->base_name) {
6453 status = NT_STATUS_NO_MEMORY;
6454 goto out;
6457 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6458 smb_fname_dst->base_name,
6459 &destname)) {
6460 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6461 smb_fname_src->base_name, destname));
6462 TALLOC_FREE(talloced);
6463 continue;
6465 if (!destname) {
6466 status = NT_STATUS_NO_MEMORY;
6467 goto out;
6470 TALLOC_FREE(smb_fname_dst->base_name);
6471 smb_fname_dst->base_name = destname;
6473 ZERO_STRUCT(smb_fname_src->st);
6474 if (posix_pathnames) {
6475 SMB_VFS_LSTAT(conn, smb_fname_src);
6476 } else {
6477 SMB_VFS_STAT(conn, smb_fname_src);
6480 create_options = 0;
6482 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6483 create_options |= FILE_DIRECTORY_FILE;
6486 status = SMB_VFS_CREATE_FILE(
6487 conn, /* conn */
6488 req, /* req */
6489 0, /* root_dir_fid */
6490 smb_fname_src, /* fname */
6491 access_mask, /* access_mask */
6492 (FILE_SHARE_READ | /* share_access */
6493 FILE_SHARE_WRITE),
6494 FILE_OPEN, /* create_disposition*/
6495 create_options, /* create_options */
6496 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6497 0, /* oplock_request */
6498 0, /* allocation_size */
6499 0, /* private_flags */
6500 NULL, /* sd */
6501 NULL, /* ea_list */
6502 &fsp, /* result */
6503 NULL); /* pinfo */
6505 if (!NT_STATUS_IS_OK(status)) {
6506 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6507 "returned %s rename %s -> %s\n",
6508 nt_errstr(status),
6509 smb_fname_str_dbg(smb_fname_src),
6510 smb_fname_str_dbg(smb_fname_dst)));
6511 break;
6514 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6515 dname);
6516 if (!smb_fname_dst->original_lcomp) {
6517 status = NT_STATUS_NO_MEMORY;
6518 goto out;
6521 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6522 attrs, replace_if_exists);
6524 close_file(req, fsp, NORMAL_CLOSE);
6526 if (!NT_STATUS_IS_OK(status)) {
6527 DEBUG(3, ("rename_internals_fsp returned %s for "
6528 "rename %s -> %s\n", nt_errstr(status),
6529 smb_fname_str_dbg(smb_fname_src),
6530 smb_fname_str_dbg(smb_fname_dst)));
6531 break;
6534 count++;
6536 DEBUG(3,("rename_internals: doing rename on %s -> "
6537 "%s\n", smb_fname_str_dbg(smb_fname_src),
6538 smb_fname_str_dbg(smb_fname_src)));
6539 TALLOC_FREE(talloced);
6541 TALLOC_FREE(dir_hnd);
6543 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6544 status = map_nt_error_from_unix(errno);
6547 out:
6548 TALLOC_FREE(talloced);
6549 TALLOC_FREE(fname_src_dir);
6550 TALLOC_FREE(fname_src_mask);
6551 return status;
6554 /****************************************************************************
6555 Reply to a mv.
6556 ****************************************************************************/
6558 void reply_mv(struct smb_request *req)
6560 connection_struct *conn = req->conn;
6561 char *name = NULL;
6562 char *newname = NULL;
6563 const char *p;
6564 uint32 attrs;
6565 NTSTATUS status;
6566 bool src_has_wcard = False;
6567 bool dest_has_wcard = False;
6568 TALLOC_CTX *ctx = talloc_tos();
6569 struct smb_filename *smb_fname_src = NULL;
6570 struct smb_filename *smb_fname_dst = NULL;
6571 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6572 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6573 bool stream_rename = false;
6575 START_PROFILE(SMBmv);
6577 if (req->wct < 1) {
6578 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6579 goto out;
6582 attrs = SVAL(req->vwv+0, 0);
6584 p = (const char *)req->buf + 1;
6585 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6586 &status, &src_has_wcard);
6587 if (!NT_STATUS_IS_OK(status)) {
6588 reply_nterror(req, status);
6589 goto out;
6591 p++;
6592 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6593 &status, &dest_has_wcard);
6594 if (!NT_STATUS_IS_OK(status)) {
6595 reply_nterror(req, status);
6596 goto out;
6599 if (!lp_posix_pathnames()) {
6600 /* The newname must begin with a ':' if the
6601 name contains a ':'. */
6602 if (strchr_m(name, ':')) {
6603 if (newname[0] != ':') {
6604 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6605 goto out;
6607 stream_rename = true;
6611 status = filename_convert(ctx,
6612 conn,
6613 req->flags2 & FLAGS2_DFS_PATHNAMES,
6614 name,
6615 src_ucf_flags,
6616 &src_has_wcard,
6617 &smb_fname_src);
6619 if (!NT_STATUS_IS_OK(status)) {
6620 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6621 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6622 ERRSRV, ERRbadpath);
6623 goto out;
6625 reply_nterror(req, status);
6626 goto out;
6629 status = filename_convert(ctx,
6630 conn,
6631 req->flags2 & FLAGS2_DFS_PATHNAMES,
6632 newname,
6633 dst_ucf_flags,
6634 &dest_has_wcard,
6635 &smb_fname_dst);
6637 if (!NT_STATUS_IS_OK(status)) {
6638 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6639 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6640 ERRSRV, ERRbadpath);
6641 goto out;
6643 reply_nterror(req, status);
6644 goto out;
6647 if (stream_rename) {
6648 /* smb_fname_dst->base_name must be the same as
6649 smb_fname_src->base_name. */
6650 TALLOC_FREE(smb_fname_dst->base_name);
6651 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6652 smb_fname_src->base_name);
6653 if (!smb_fname_dst->base_name) {
6654 reply_nterror(req, NT_STATUS_NO_MEMORY);
6655 goto out;
6659 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6660 smb_fname_str_dbg(smb_fname_dst)));
6662 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6663 attrs, False, src_has_wcard, dest_has_wcard,
6664 DELETE_ACCESS);
6665 if (!NT_STATUS_IS_OK(status)) {
6666 if (open_was_deferred(req->sconn, req->mid)) {
6667 /* We have re-scheduled this call. */
6668 goto out;
6670 reply_nterror(req, status);
6671 goto out;
6674 reply_outbuf(req, 0, 0);
6675 out:
6676 TALLOC_FREE(smb_fname_src);
6677 TALLOC_FREE(smb_fname_dst);
6678 END_PROFILE(SMBmv);
6679 return;
6682 /*******************************************************************
6683 Copy a file as part of a reply_copy.
6684 ******************************************************************/
6687 * TODO: check error codes on all callers
6690 NTSTATUS copy_file(TALLOC_CTX *ctx,
6691 connection_struct *conn,
6692 struct smb_filename *smb_fname_src,
6693 struct smb_filename *smb_fname_dst,
6694 int ofun,
6695 int count,
6696 bool target_is_directory)
6698 struct smb_filename *smb_fname_dst_tmp = NULL;
6699 off_t ret=-1;
6700 files_struct *fsp1,*fsp2;
6701 uint32 dosattrs;
6702 uint32 new_create_disposition;
6703 NTSTATUS status;
6706 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6707 if (!NT_STATUS_IS_OK(status)) {
6708 return status;
6712 * If the target is a directory, extract the last component from the
6713 * src filename and append it to the dst filename
6715 if (target_is_directory) {
6716 const char *p;
6718 /* dest/target can't be a stream if it's a directory. */
6719 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6721 p = strrchr_m(smb_fname_src->base_name,'/');
6722 if (p) {
6723 p++;
6724 } else {
6725 p = smb_fname_src->base_name;
6727 smb_fname_dst_tmp->base_name =
6728 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6730 if (!smb_fname_dst_tmp->base_name) {
6731 status = NT_STATUS_NO_MEMORY;
6732 goto out;
6736 status = vfs_file_exist(conn, smb_fname_src);
6737 if (!NT_STATUS_IS_OK(status)) {
6738 goto out;
6741 if (!target_is_directory && count) {
6742 new_create_disposition = FILE_OPEN;
6743 } else {
6744 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6745 0, ofun,
6746 NULL, NULL,
6747 &new_create_disposition,
6748 NULL,
6749 NULL)) {
6750 status = NT_STATUS_INVALID_PARAMETER;
6751 goto out;
6755 /* Open the src file for reading. */
6756 status = SMB_VFS_CREATE_FILE(
6757 conn, /* conn */
6758 NULL, /* req */
6759 0, /* root_dir_fid */
6760 smb_fname_src, /* fname */
6761 FILE_GENERIC_READ, /* access_mask */
6762 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6763 FILE_OPEN, /* create_disposition*/
6764 0, /* create_options */
6765 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6766 INTERNAL_OPEN_ONLY, /* oplock_request */
6767 0, /* allocation_size */
6768 0, /* private_flags */
6769 NULL, /* sd */
6770 NULL, /* ea_list */
6771 &fsp1, /* result */
6772 NULL); /* psbuf */
6774 if (!NT_STATUS_IS_OK(status)) {
6775 goto out;
6778 dosattrs = dos_mode(conn, smb_fname_src);
6780 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6781 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6784 /* Open the dst file for writing. */
6785 status = SMB_VFS_CREATE_FILE(
6786 conn, /* conn */
6787 NULL, /* req */
6788 0, /* root_dir_fid */
6789 smb_fname_dst, /* fname */
6790 FILE_GENERIC_WRITE, /* access_mask */
6791 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6792 new_create_disposition, /* create_disposition*/
6793 0, /* create_options */
6794 dosattrs, /* file_attributes */
6795 INTERNAL_OPEN_ONLY, /* oplock_request */
6796 0, /* allocation_size */
6797 0, /* private_flags */
6798 NULL, /* sd */
6799 NULL, /* ea_list */
6800 &fsp2, /* result */
6801 NULL); /* psbuf */
6803 if (!NT_STATUS_IS_OK(status)) {
6804 close_file(NULL, fsp1, ERROR_CLOSE);
6805 goto out;
6808 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6809 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6810 if (ret == -1) {
6811 DEBUG(0, ("error - vfs lseek returned error %s\n",
6812 strerror(errno)));
6813 status = map_nt_error_from_unix(errno);
6814 close_file(NULL, fsp1, ERROR_CLOSE);
6815 close_file(NULL, fsp2, ERROR_CLOSE);
6816 goto out;
6820 /* Do the actual copy. */
6821 if (smb_fname_src->st.st_ex_size) {
6822 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6823 } else {
6824 ret = 0;
6827 close_file(NULL, fsp1, NORMAL_CLOSE);
6829 /* Ensure the modtime is set correctly on the destination file. */
6830 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6833 * As we are opening fsp1 read-only we only expect
6834 * an error on close on fsp2 if we are out of space.
6835 * Thus we don't look at the error return from the
6836 * close of fsp1.
6838 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6840 if (!NT_STATUS_IS_OK(status)) {
6841 goto out;
6844 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
6845 status = NT_STATUS_DISK_FULL;
6846 goto out;
6849 status = NT_STATUS_OK;
6851 out:
6852 TALLOC_FREE(smb_fname_dst_tmp);
6853 return status;
6856 /****************************************************************************
6857 Reply to a file copy.
6858 ****************************************************************************/
6860 void reply_copy(struct smb_request *req)
6862 connection_struct *conn = req->conn;
6863 struct smb_filename *smb_fname_src = NULL;
6864 struct smb_filename *smb_fname_dst = NULL;
6865 char *fname_src = NULL;
6866 char *fname_dst = NULL;
6867 char *fname_src_mask = NULL;
6868 char *fname_src_dir = NULL;
6869 const char *p;
6870 int count=0;
6871 int error = ERRnoaccess;
6872 int tid2;
6873 int ofun;
6874 int flags;
6875 bool target_is_directory=False;
6876 bool source_has_wild = False;
6877 bool dest_has_wild = False;
6878 NTSTATUS status;
6879 TALLOC_CTX *ctx = talloc_tos();
6881 START_PROFILE(SMBcopy);
6883 if (req->wct < 3) {
6884 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6885 goto out;
6888 tid2 = SVAL(req->vwv+0, 0);
6889 ofun = SVAL(req->vwv+1, 0);
6890 flags = SVAL(req->vwv+2, 0);
6892 p = (const char *)req->buf;
6893 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6894 &status, &source_has_wild);
6895 if (!NT_STATUS_IS_OK(status)) {
6896 reply_nterror(req, status);
6897 goto out;
6899 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6900 &status, &dest_has_wild);
6901 if (!NT_STATUS_IS_OK(status)) {
6902 reply_nterror(req, status);
6903 goto out;
6906 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6908 if (tid2 != conn->cnum) {
6909 /* can't currently handle inter share copies XXXX */
6910 DEBUG(3,("Rejecting inter-share copy\n"));
6911 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6912 goto out;
6915 status = filename_convert(ctx, conn,
6916 req->flags2 & FLAGS2_DFS_PATHNAMES,
6917 fname_src,
6918 UCF_COND_ALLOW_WCARD_LCOMP,
6919 &source_has_wild,
6920 &smb_fname_src);
6921 if (!NT_STATUS_IS_OK(status)) {
6922 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6923 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6924 ERRSRV, ERRbadpath);
6925 goto out;
6927 reply_nterror(req, status);
6928 goto out;
6931 status = filename_convert(ctx, conn,
6932 req->flags2 & FLAGS2_DFS_PATHNAMES,
6933 fname_dst,
6934 UCF_COND_ALLOW_WCARD_LCOMP,
6935 &dest_has_wild,
6936 &smb_fname_dst);
6937 if (!NT_STATUS_IS_OK(status)) {
6938 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6939 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6940 ERRSRV, ERRbadpath);
6941 goto out;
6943 reply_nterror(req, status);
6944 goto out;
6947 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6949 if ((flags&1) && target_is_directory) {
6950 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6951 goto out;
6954 if ((flags&2) && !target_is_directory) {
6955 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6956 goto out;
6959 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6960 /* wants a tree copy! XXXX */
6961 DEBUG(3,("Rejecting tree copy\n"));
6962 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6963 goto out;
6966 /* Split up the directory from the filename/mask. */
6967 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6968 &fname_src_dir, &fname_src_mask);
6969 if (!NT_STATUS_IS_OK(status)) {
6970 reply_nterror(req, NT_STATUS_NO_MEMORY);
6971 goto out;
6975 * We should only check the mangled cache
6976 * here if unix_convert failed. This means
6977 * that the path in 'mask' doesn't exist
6978 * on the file system and so we need to look
6979 * for a possible mangle. This patch from
6980 * Tine Smukavec <valentin.smukavec@hermes.si>.
6982 if (!VALID_STAT(smb_fname_src->st) &&
6983 mangle_is_mangled(fname_src_mask, conn->params)) {
6984 char *new_mask = NULL;
6985 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6986 &new_mask, conn->params);
6988 /* Use demangled name if one was successfully found. */
6989 if (new_mask) {
6990 TALLOC_FREE(fname_src_mask);
6991 fname_src_mask = new_mask;
6995 if (!source_has_wild) {
6998 * Only one file needs to be copied. Append the mask back onto
6999 * the directory.
7001 TALLOC_FREE(smb_fname_src->base_name);
7002 if (ISDOT(fname_src_dir)) {
7003 /* Ensure we use canonical names on open. */
7004 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7005 "%s",
7006 fname_src_mask);
7007 } else {
7008 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7009 "%s/%s",
7010 fname_src_dir,
7011 fname_src_mask);
7013 if (!smb_fname_src->base_name) {
7014 reply_nterror(req, NT_STATUS_NO_MEMORY);
7015 goto out;
7018 if (dest_has_wild) {
7019 char *fname_dst_mod = NULL;
7020 if (!resolve_wildcards(smb_fname_dst,
7021 smb_fname_src->base_name,
7022 smb_fname_dst->base_name,
7023 &fname_dst_mod)) {
7024 reply_nterror(req, NT_STATUS_NO_MEMORY);
7025 goto out;
7027 TALLOC_FREE(smb_fname_dst->base_name);
7028 smb_fname_dst->base_name = fname_dst_mod;
7031 status = check_name(conn, smb_fname_src->base_name);
7032 if (!NT_STATUS_IS_OK(status)) {
7033 reply_nterror(req, status);
7034 goto out;
7037 status = check_name(conn, smb_fname_dst->base_name);
7038 if (!NT_STATUS_IS_OK(status)) {
7039 reply_nterror(req, status);
7040 goto out;
7043 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7044 ofun, count, target_is_directory);
7046 if(!NT_STATUS_IS_OK(status)) {
7047 reply_nterror(req, status);
7048 goto out;
7049 } else {
7050 count++;
7052 } else {
7053 struct smb_Dir *dir_hnd = NULL;
7054 const char *dname = NULL;
7055 char *talloced = NULL;
7056 long offset = 0;
7059 * There is a wildcard that requires us to actually read the
7060 * src dir and copy each file matching the mask to the dst.
7061 * Right now streams won't be copied, but this could
7062 * presumably be added with a nested loop for reach dir entry.
7064 SMB_ASSERT(!smb_fname_src->stream_name);
7065 SMB_ASSERT(!smb_fname_dst->stream_name);
7067 smb_fname_src->stream_name = NULL;
7068 smb_fname_dst->stream_name = NULL;
7070 if (strequal(fname_src_mask,"????????.???")) {
7071 TALLOC_FREE(fname_src_mask);
7072 fname_src_mask = talloc_strdup(ctx, "*");
7073 if (!fname_src_mask) {
7074 reply_nterror(req, NT_STATUS_NO_MEMORY);
7075 goto out;
7079 status = check_name(conn, fname_src_dir);
7080 if (!NT_STATUS_IS_OK(status)) {
7081 reply_nterror(req, status);
7082 goto out;
7085 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7086 if (dir_hnd == NULL) {
7087 status = map_nt_error_from_unix(errno);
7088 reply_nterror(req, status);
7089 goto out;
7092 error = ERRbadfile;
7094 /* Iterate over the src dir copying each entry to the dst. */
7095 while ((dname = ReadDirName(dir_hnd, &offset,
7096 &smb_fname_src->st, &talloced))) {
7097 char *destname = NULL;
7099 if (ISDOT(dname) || ISDOTDOT(dname)) {
7100 TALLOC_FREE(talloced);
7101 continue;
7104 if (!is_visible_file(conn, fname_src_dir, dname,
7105 &smb_fname_src->st, false)) {
7106 TALLOC_FREE(talloced);
7107 continue;
7110 if(!mask_match(dname, fname_src_mask,
7111 conn->case_sensitive)) {
7112 TALLOC_FREE(talloced);
7113 continue;
7116 error = ERRnoaccess;
7118 /* Get the src smb_fname struct setup. */
7119 TALLOC_FREE(smb_fname_src->base_name);
7120 if (ISDOT(fname_src_dir)) {
7121 /* Ensure we use canonical names on open. */
7122 smb_fname_src->base_name =
7123 talloc_asprintf(smb_fname_src, "%s",
7124 dname);
7125 } else {
7126 smb_fname_src->base_name =
7127 talloc_asprintf(smb_fname_src, "%s/%s",
7128 fname_src_dir, dname);
7131 if (!smb_fname_src->base_name) {
7132 TALLOC_FREE(dir_hnd);
7133 TALLOC_FREE(talloced);
7134 reply_nterror(req, NT_STATUS_NO_MEMORY);
7135 goto out;
7138 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7139 smb_fname_dst->base_name,
7140 &destname)) {
7141 TALLOC_FREE(talloced);
7142 continue;
7144 if (!destname) {
7145 TALLOC_FREE(dir_hnd);
7146 TALLOC_FREE(talloced);
7147 reply_nterror(req, NT_STATUS_NO_MEMORY);
7148 goto out;
7151 TALLOC_FREE(smb_fname_dst->base_name);
7152 smb_fname_dst->base_name = destname;
7154 status = check_name(conn, smb_fname_src->base_name);
7155 if (!NT_STATUS_IS_OK(status)) {
7156 TALLOC_FREE(dir_hnd);
7157 TALLOC_FREE(talloced);
7158 reply_nterror(req, status);
7159 goto out;
7162 status = check_name(conn, smb_fname_dst->base_name);
7163 if (!NT_STATUS_IS_OK(status)) {
7164 TALLOC_FREE(dir_hnd);
7165 TALLOC_FREE(talloced);
7166 reply_nterror(req, status);
7167 goto out;
7170 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7171 smb_fname_src->base_name,
7172 smb_fname_dst->base_name));
7174 status = copy_file(ctx, conn, smb_fname_src,
7175 smb_fname_dst, ofun, count,
7176 target_is_directory);
7177 if (NT_STATUS_IS_OK(status)) {
7178 count++;
7181 TALLOC_FREE(talloced);
7183 TALLOC_FREE(dir_hnd);
7186 if (count == 0) {
7187 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7188 goto out;
7191 reply_outbuf(req, 1, 0);
7192 SSVAL(req->outbuf,smb_vwv0,count);
7193 out:
7194 TALLOC_FREE(smb_fname_src);
7195 TALLOC_FREE(smb_fname_dst);
7196 TALLOC_FREE(fname_src);
7197 TALLOC_FREE(fname_dst);
7198 TALLOC_FREE(fname_src_mask);
7199 TALLOC_FREE(fname_src_dir);
7201 END_PROFILE(SMBcopy);
7202 return;
7205 #undef DBGC_CLASS
7206 #define DBGC_CLASS DBGC_LOCKING
7208 /****************************************************************************
7209 Get a lock pid, dealing with large count requests.
7210 ****************************************************************************/
7212 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7213 bool large_file_format)
7215 if(!large_file_format)
7216 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7217 else
7218 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7221 /****************************************************************************
7222 Get a lock count, dealing with large count requests.
7223 ****************************************************************************/
7225 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7226 bool large_file_format)
7228 uint64_t count = 0;
7230 if(!large_file_format) {
7231 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7232 } else {
7234 #if defined(HAVE_LONGLONG)
7235 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7236 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7237 #else /* HAVE_LONGLONG */
7240 * NT4.x seems to be broken in that it sends large file (64 bit)
7241 * lockingX calls even if the CAP_LARGE_FILES was *not*
7242 * negotiated. For boxes without large unsigned ints truncate the
7243 * lock count by dropping the top 32 bits.
7246 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7247 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7248 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7249 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7250 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7253 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7254 #endif /* HAVE_LONGLONG */
7257 return count;
7260 #if !defined(HAVE_LONGLONG)
7261 /****************************************************************************
7262 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7263 ****************************************************************************/
7265 static uint32 map_lock_offset(uint32 high, uint32 low)
7267 unsigned int i;
7268 uint32 mask = 0;
7269 uint32 highcopy = high;
7272 * Try and find out how many significant bits there are in high.
7275 for(i = 0; highcopy; i++)
7276 highcopy >>= 1;
7279 * We use 31 bits not 32 here as POSIX
7280 * lock offsets may not be negative.
7283 mask = (~0) << (31 - i);
7285 if(low & mask)
7286 return 0; /* Fail. */
7288 high <<= (31 - i);
7290 return (high|low);
7292 #endif /* !defined(HAVE_LONGLONG) */
7294 /****************************************************************************
7295 Get a lock offset, dealing with large offset requests.
7296 ****************************************************************************/
7298 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7299 bool large_file_format, bool *err)
7301 uint64_t offset = 0;
7303 *err = False;
7305 if(!large_file_format) {
7306 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7307 } else {
7309 #if defined(HAVE_LONGLONG)
7310 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7311 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7312 #else /* HAVE_LONGLONG */
7315 * NT4.x seems to be broken in that it sends large file (64 bit)
7316 * lockingX calls even if the CAP_LARGE_FILES was *not*
7317 * negotiated. For boxes without large unsigned ints mangle the
7318 * lock offset by mapping the top 32 bits onto the lower 32.
7321 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7322 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7323 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7324 uint32 new_low = 0;
7326 if((new_low = map_lock_offset(high, low)) == 0) {
7327 *err = True;
7328 return (uint64_t)-1;
7331 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7332 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7333 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7334 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7337 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7338 #endif /* HAVE_LONGLONG */
7341 return offset;
7344 NTSTATUS smbd_do_locking(struct smb_request *req,
7345 files_struct *fsp,
7346 uint8_t type,
7347 int32_t timeout,
7348 uint16_t num_ulocks,
7349 struct smbd_lock_element *ulocks,
7350 uint16_t num_locks,
7351 struct smbd_lock_element *locks,
7352 bool *async)
7354 connection_struct *conn = req->conn;
7355 int i;
7356 NTSTATUS status = NT_STATUS_OK;
7358 *async = false;
7360 /* Data now points at the beginning of the list
7361 of smb_unlkrng structs */
7362 for(i = 0; i < (int)num_ulocks; i++) {
7363 struct smbd_lock_element *e = &ulocks[i];
7365 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7366 "pid %u, file %s\n",
7367 (double)e->offset,
7368 (double)e->count,
7369 (unsigned int)e->smblctx,
7370 fsp_str_dbg(fsp)));
7372 if (e->brltype != UNLOCK_LOCK) {
7373 /* this can only happen with SMB2 */
7374 return NT_STATUS_INVALID_PARAMETER;
7377 status = do_unlock(req->sconn->msg_ctx,
7378 fsp,
7379 e->smblctx,
7380 e->count,
7381 e->offset,
7382 WINDOWS_LOCK);
7384 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7385 nt_errstr(status)));
7387 if (!NT_STATUS_IS_OK(status)) {
7388 return status;
7392 /* Setup the timeout in seconds. */
7394 if (!lp_blocking_locks(SNUM(conn))) {
7395 timeout = 0;
7398 /* Data now points at the beginning of the list
7399 of smb_lkrng structs */
7401 for(i = 0; i < (int)num_locks; i++) {
7402 struct smbd_lock_element *e = &locks[i];
7404 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7405 "%llu, file %s timeout = %d\n",
7406 (double)e->offset,
7407 (double)e->count,
7408 (unsigned long long)e->smblctx,
7409 fsp_str_dbg(fsp),
7410 (int)timeout));
7412 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7413 struct blocking_lock_record *blr = NULL;
7415 if (num_locks > 1) {
7417 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7418 * if the lock vector contains one entry. When given mutliple cancel
7419 * requests in a single PDU we expect the server to return an
7420 * error. Windows servers seem to accept the request but only
7421 * cancel the first lock.
7422 * JRA - Do what Windows does (tm) :-).
7425 #if 0
7426 /* MS-CIFS (2.2.4.32.1) behavior. */
7427 return NT_STATUS_DOS(ERRDOS,
7428 ERRcancelviolation);
7429 #else
7430 /* Windows behavior. */
7431 if (i != 0) {
7432 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7433 "cancel request\n"));
7434 continue;
7436 #endif
7439 if (lp_blocking_locks(SNUM(conn))) {
7441 /* Schedule a message to ourselves to
7442 remove the blocking lock record and
7443 return the right error. */
7445 blr = blocking_lock_cancel_smb1(fsp,
7446 e->smblctx,
7447 e->offset,
7448 e->count,
7449 WINDOWS_LOCK,
7450 type,
7451 NT_STATUS_FILE_LOCK_CONFLICT);
7452 if (blr == NULL) {
7453 return NT_STATUS_DOS(
7454 ERRDOS,
7455 ERRcancelviolation);
7458 /* Remove a matching pending lock. */
7459 status = do_lock_cancel(fsp,
7460 e->smblctx,
7461 e->count,
7462 e->offset,
7463 WINDOWS_LOCK,
7464 blr);
7465 } else {
7466 bool blocking_lock = timeout ? true : false;
7467 bool defer_lock = false;
7468 struct byte_range_lock *br_lck;
7469 uint64_t block_smblctx;
7471 br_lck = do_lock(req->sconn->msg_ctx,
7472 fsp,
7473 e->smblctx,
7474 e->count,
7475 e->offset,
7476 e->brltype,
7477 WINDOWS_LOCK,
7478 blocking_lock,
7479 &status,
7480 &block_smblctx,
7481 NULL);
7483 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7484 /* Windows internal resolution for blocking locks seems
7485 to be about 200ms... Don't wait for less than that. JRA. */
7486 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7487 timeout = lp_lock_spin_time();
7489 defer_lock = true;
7492 /* If a lock sent with timeout of zero would fail, and
7493 * this lock has been requested multiple times,
7494 * according to brl_lock_failed() we convert this
7495 * request to a blocking lock with a timeout of between
7496 * 150 - 300 milliseconds.
7498 * If lp_lock_spin_time() has been set to 0, we skip
7499 * this blocking retry and fail immediately.
7501 * Replacement for do_lock_spin(). JRA. */
7503 if (!req->sconn->using_smb2 &&
7504 br_lck && lp_blocking_locks(SNUM(conn)) &&
7505 lp_lock_spin_time() && !blocking_lock &&
7506 NT_STATUS_EQUAL((status),
7507 NT_STATUS_FILE_LOCK_CONFLICT))
7509 defer_lock = true;
7510 timeout = lp_lock_spin_time();
7513 if (br_lck && defer_lock) {
7515 * A blocking lock was requested. Package up
7516 * this smb into a queued request and push it
7517 * onto the blocking lock queue.
7519 if(push_blocking_lock_request(br_lck,
7520 req,
7521 fsp,
7522 timeout,
7524 e->smblctx,
7525 e->brltype,
7526 WINDOWS_LOCK,
7527 e->offset,
7528 e->count,
7529 block_smblctx)) {
7530 TALLOC_FREE(br_lck);
7531 *async = true;
7532 return NT_STATUS_OK;
7536 TALLOC_FREE(br_lck);
7539 if (!NT_STATUS_IS_OK(status)) {
7540 break;
7544 /* If any of the above locks failed, then we must unlock
7545 all of the previous locks (X/Open spec). */
7547 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7549 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7550 i = -1; /* we want to skip the for loop */
7554 * Ensure we don't do a remove on the lock that just failed,
7555 * as under POSIX rules, if we have a lock already there, we
7556 * will delete it (and we shouldn't) .....
7558 for(i--; i >= 0; i--) {
7559 struct smbd_lock_element *e = &locks[i];
7561 do_unlock(req->sconn->msg_ctx,
7562 fsp,
7563 e->smblctx,
7564 e->count,
7565 e->offset,
7566 WINDOWS_LOCK);
7568 return status;
7571 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7572 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7574 return NT_STATUS_OK;
7577 /****************************************************************************
7578 Reply to a lockingX request.
7579 ****************************************************************************/
7581 void reply_lockingX(struct smb_request *req)
7583 connection_struct *conn = req->conn;
7584 files_struct *fsp;
7585 unsigned char locktype;
7586 unsigned char oplocklevel;
7587 uint16 num_ulocks;
7588 uint16 num_locks;
7589 int32 lock_timeout;
7590 int i;
7591 const uint8_t *data;
7592 bool large_file_format;
7593 bool err;
7594 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7595 struct smbd_lock_element *ulocks;
7596 struct smbd_lock_element *locks;
7597 bool async = false;
7599 START_PROFILE(SMBlockingX);
7601 if (req->wct < 8) {
7602 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7603 END_PROFILE(SMBlockingX);
7604 return;
7607 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7608 locktype = CVAL(req->vwv+3, 0);
7609 oplocklevel = CVAL(req->vwv+3, 1);
7610 num_ulocks = SVAL(req->vwv+6, 0);
7611 num_locks = SVAL(req->vwv+7, 0);
7612 lock_timeout = IVAL(req->vwv+4, 0);
7613 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7615 if (!check_fsp(conn, req, fsp)) {
7616 END_PROFILE(SMBlockingX);
7617 return;
7620 data = req->buf;
7622 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7623 /* we don't support these - and CANCEL_LOCK makes w2k
7624 and XP reboot so I don't really want to be
7625 compatible! (tridge) */
7626 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7627 END_PROFILE(SMBlockingX);
7628 return;
7631 /* Check if this is an oplock break on a file
7632 we have granted an oplock on.
7634 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7635 /* Client can insist on breaking to none. */
7636 bool break_to_none = (oplocklevel == 0);
7637 bool result;
7639 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7640 "for fnum = %d\n", (unsigned int)oplocklevel,
7641 fsp->fnum ));
7644 * Make sure we have granted an exclusive or batch oplock on
7645 * this file.
7648 if (fsp->oplock_type == 0) {
7650 /* The Samba4 nbench simulator doesn't understand
7651 the difference between break to level2 and break
7652 to none from level2 - it sends oplock break
7653 replies in both cases. Don't keep logging an error
7654 message here - just ignore it. JRA. */
7656 DEBUG(5,("reply_lockingX: Error : oplock break from "
7657 "client for fnum = %d (oplock=%d) and no "
7658 "oplock granted on this file (%s).\n",
7659 fsp->fnum, fsp->oplock_type,
7660 fsp_str_dbg(fsp)));
7662 /* if this is a pure oplock break request then don't
7663 * send a reply */
7664 if (num_locks == 0 && num_ulocks == 0) {
7665 END_PROFILE(SMBlockingX);
7666 return;
7667 } else {
7668 END_PROFILE(SMBlockingX);
7669 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7670 return;
7674 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7675 (break_to_none)) {
7676 result = remove_oplock(fsp);
7677 } else {
7678 result = downgrade_oplock(fsp);
7681 if (!result) {
7682 DEBUG(0, ("reply_lockingX: error in removing "
7683 "oplock on file %s\n", fsp_str_dbg(fsp)));
7684 /* Hmmm. Is this panic justified? */
7685 smb_panic("internal tdb error");
7688 reply_to_oplock_break_requests(fsp);
7690 /* if this is a pure oplock break request then don't send a
7691 * reply */
7692 if (num_locks == 0 && num_ulocks == 0) {
7693 /* Sanity check - ensure a pure oplock break is not a
7694 chained request. */
7695 if(CVAL(req->vwv+0, 0) != 0xff)
7696 DEBUG(0,("reply_lockingX: Error : pure oplock "
7697 "break is a chained %d request !\n",
7698 (unsigned int)CVAL(req->vwv+0, 0)));
7699 END_PROFILE(SMBlockingX);
7700 return;
7704 if (req->buflen <
7705 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7706 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7707 END_PROFILE(SMBlockingX);
7708 return;
7711 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7712 if (ulocks == NULL) {
7713 reply_nterror(req, NT_STATUS_NO_MEMORY);
7714 END_PROFILE(SMBlockingX);
7715 return;
7718 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7719 if (locks == NULL) {
7720 reply_nterror(req, NT_STATUS_NO_MEMORY);
7721 END_PROFILE(SMBlockingX);
7722 return;
7725 /* Data now points at the beginning of the list
7726 of smb_unlkrng structs */
7727 for(i = 0; i < (int)num_ulocks; i++) {
7728 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7729 ulocks[i].count = get_lock_count(data, i, large_file_format);
7730 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7731 ulocks[i].brltype = UNLOCK_LOCK;
7734 * There is no error code marked "stupid client bug".... :-).
7736 if(err) {
7737 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7738 END_PROFILE(SMBlockingX);
7739 return;
7743 /* Now do any requested locks */
7744 data += ((large_file_format ? 20 : 10)*num_ulocks);
7746 /* Data now points at the beginning of the list
7747 of smb_lkrng structs */
7749 for(i = 0; i < (int)num_locks; i++) {
7750 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7751 locks[i].count = get_lock_count(data, i, large_file_format);
7752 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7754 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7755 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7756 locks[i].brltype = PENDING_READ_LOCK;
7757 } else {
7758 locks[i].brltype = READ_LOCK;
7760 } else {
7761 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7762 locks[i].brltype = PENDING_WRITE_LOCK;
7763 } else {
7764 locks[i].brltype = WRITE_LOCK;
7769 * There is no error code marked "stupid client bug".... :-).
7771 if(err) {
7772 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7773 END_PROFILE(SMBlockingX);
7774 return;
7778 status = smbd_do_locking(req, fsp,
7779 locktype, lock_timeout,
7780 num_ulocks, ulocks,
7781 num_locks, locks,
7782 &async);
7783 if (!NT_STATUS_IS_OK(status)) {
7784 END_PROFILE(SMBlockingX);
7785 reply_nterror(req, status);
7786 return;
7788 if (async) {
7789 END_PROFILE(SMBlockingX);
7790 return;
7793 reply_outbuf(req, 2, 0);
7794 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
7795 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
7797 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7798 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7800 END_PROFILE(SMBlockingX);
7803 #undef DBGC_CLASS
7804 #define DBGC_CLASS DBGC_ALL
7806 /****************************************************************************
7807 Reply to a SMBreadbmpx (read block multiplex) request.
7808 Always reply with an error, if someone has a platform really needs this,
7809 please contact vl@samba.org
7810 ****************************************************************************/
7812 void reply_readbmpx(struct smb_request *req)
7814 START_PROFILE(SMBreadBmpx);
7815 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7816 END_PROFILE(SMBreadBmpx);
7817 return;
7820 /****************************************************************************
7821 Reply to a SMBreadbs (read block multiplex secondary) request.
7822 Always reply with an error, if someone has a platform really needs this,
7823 please contact vl@samba.org
7824 ****************************************************************************/
7826 void reply_readbs(struct smb_request *req)
7828 START_PROFILE(SMBreadBs);
7829 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7830 END_PROFILE(SMBreadBs);
7831 return;
7834 /****************************************************************************
7835 Reply to a SMBsetattrE.
7836 ****************************************************************************/
7838 void reply_setattrE(struct smb_request *req)
7840 connection_struct *conn = req->conn;
7841 struct smb_file_time ft;
7842 files_struct *fsp;
7843 NTSTATUS status;
7845 START_PROFILE(SMBsetattrE);
7846 ZERO_STRUCT(ft);
7848 if (req->wct < 7) {
7849 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7850 goto out;
7853 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7855 if(!fsp || (fsp->conn != conn)) {
7856 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7857 goto out;
7861 * Convert the DOS times into unix times.
7864 ft.atime = convert_time_t_to_timespec(
7865 srv_make_unix_date2(req->vwv+3));
7866 ft.mtime = convert_time_t_to_timespec(
7867 srv_make_unix_date2(req->vwv+5));
7868 ft.create_time = convert_time_t_to_timespec(
7869 srv_make_unix_date2(req->vwv+1));
7871 reply_outbuf(req, 0, 0);
7874 * Patch from Ray Frush <frush@engr.colostate.edu>
7875 * Sometimes times are sent as zero - ignore them.
7878 /* Ensure we have a valid stat struct for the source. */
7879 status = vfs_stat_fsp(fsp);
7880 if (!NT_STATUS_IS_OK(status)) {
7881 reply_nterror(req, status);
7882 goto out;
7885 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
7886 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7887 goto out;
7890 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7891 if (!NT_STATUS_IS_OK(status)) {
7892 reply_nterror(req, status);
7893 goto out;
7896 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7897 " createtime=%u\n",
7898 fsp->fnum,
7899 (unsigned int)ft.atime.tv_sec,
7900 (unsigned int)ft.mtime.tv_sec,
7901 (unsigned int)ft.create_time.tv_sec
7903 out:
7904 END_PROFILE(SMBsetattrE);
7905 return;
7909 /* Back from the dead for OS/2..... JRA. */
7911 /****************************************************************************
7912 Reply to a SMBwritebmpx (write block multiplex primary) request.
7913 Always reply with an error, if someone has a platform really needs this,
7914 please contact vl@samba.org
7915 ****************************************************************************/
7917 void reply_writebmpx(struct smb_request *req)
7919 START_PROFILE(SMBwriteBmpx);
7920 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7921 END_PROFILE(SMBwriteBmpx);
7922 return;
7925 /****************************************************************************
7926 Reply to a SMBwritebs (write block multiplex secondary) request.
7927 Always reply with an error, if someone has a platform really needs this,
7928 please contact vl@samba.org
7929 ****************************************************************************/
7931 void reply_writebs(struct smb_request *req)
7933 START_PROFILE(SMBwriteBs);
7934 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7935 END_PROFILE(SMBwriteBs);
7936 return;
7939 /****************************************************************************
7940 Reply to a SMBgetattrE.
7941 ****************************************************************************/
7943 void reply_getattrE(struct smb_request *req)
7945 connection_struct *conn = req->conn;
7946 int mode;
7947 files_struct *fsp;
7948 struct timespec create_ts;
7950 START_PROFILE(SMBgetattrE);
7952 if (req->wct < 1) {
7953 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7954 END_PROFILE(SMBgetattrE);
7955 return;
7958 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7960 if(!fsp || (fsp->conn != conn)) {
7961 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7962 END_PROFILE(SMBgetattrE);
7963 return;
7966 /* Do an fstat on this file */
7967 if(fsp_stat(fsp)) {
7968 reply_nterror(req, map_nt_error_from_unix(errno));
7969 END_PROFILE(SMBgetattrE);
7970 return;
7973 mode = dos_mode(conn, fsp->fsp_name);
7976 * Convert the times into dos times. Set create
7977 * date to be last modify date as UNIX doesn't save
7978 * this.
7981 reply_outbuf(req, 11, 0);
7983 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7984 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7985 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7986 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7987 /* Should we check pending modtime here ? JRA */
7988 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7989 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7991 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
7992 SIVAL(req->outbuf, smb_vwv6, 0);
7993 SIVAL(req->outbuf, smb_vwv8, 0);
7994 } else {
7995 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7996 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7997 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7999 SSVAL(req->outbuf,smb_vwv10, mode);
8001 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
8003 END_PROFILE(SMBgetattrE);
8004 return;